質問: 非静的 public final フィールドの是非 こんにちは。c# & java初心者です。 (長文になるのでその心積もりを) 数ヶ月前まではc#一本だったのですが、そろそろ多言語に触れるには頃合かと思い、javaを始めました。 c#ではほとんどタブーとされる非静的protectedまたはpublicフィールドですが、javaの配列では、public final int lengthの形で存在します(実にカルチャーショックでした)。 c#はやたらややこしいのがあるらしく、たとえreadonly(final)でも非静的なら、特殊なクラスか何かを使えば書き換え可能らしいので、readonly(final)でもpublicまたはprotectedにしてはいけないのがルールらしいです(少なくともライブラリ設計では)。 また、「コードアクセスセキュリティ要求によって保護されない」とかいうさらに面倒な理由もあるとか。 ともかく、javaにはそういうのがないのか、平然と非静的public final フィールドが存在します。 静的にしろ、非静的にしろ、finalでないフィールドを公開するのは、javaでも、どう考えてもご法度なのは、分かります。 静的なら、finalにしておけば定数とほぼ同じ扱いができるのもc#と変わらないので(c#にはconstがありますが)、これも分かります。 しかし、finalにすれば非静的でもpublicまたはprotectedにしてもよいのかということには疑問符です。 気になる点は4つ。 1つは、本当にセキュリティーの問題がないかどうか。つまり、書き換えられたりする恐れがないかどうか。 2つは、保守性の問題。つまり、後から変更があった際に、メソッドならその内容を変えて、そのクラスだけをコンパイルすればよいが、フィールドなら関連する全てのクラスを直し、再コンパイルする必要があること。 例えば、年齢をフィールドに持つ仕様から、生年月日を記録し、そこから年齢を取得するプロパティ(メソッド)を使う仕様に変わった場合など。 3つは、統一性の問題。javaにある配列のlengthフィールドと、stringクラスのlength()メソッドの使い方の揺れを代表するように、「こちらはフィールドなのに、こちらはメソッド」のような気持ちの悪い作りのために、使用者が困惑したり、不便さを感じたりしないか(特にはじめたての初心者、それも対したideやエディター使っていない人々に悪影響を及ぼさないか。えっ!? オ、オレじゃねぇ! オレはやってない!)。 最後はインターフェイスとの関係。これは2つめの保守性にもかかわる部分ですが、クラスが完成しかけた状態または、完成した後にインターフェイスを実装して使用するような仕様変更があった場合、例えば、sizeフィールドを持つクラスに、size()メソッドを持つインターフェイスを実装することになった場合です。 その場合、javaにはc#でいうところの明示的実装がないらしく、暗黙的実装しかないようなので、sizeフィールドと、size()メソッドの両方を残すという気持ちの悪い形になるか、sizeフィールドをなくし(または隠蔽)、外部の呼び出しを全てsize()メソッドに書き換えていくか、という2択になります。 class sample { public final int size; //それ以外は省略 } があって、 interface sampleinterface { public int size(); //それ以外は省略 } を実装しなければいけなくなった場合、 class sample implements sampleinterface { public final int size; public int size() { return size; } //それ以外は省略 } または class sample implements sampleinterface { private final int size; public int size() { return size; } //それ以外は省略 } ちなみにc#であればこんな感じ(飽くまでイメージ) class sample implements sampleinterface { public final int size; // publicのまま int sampleinterface.size() { return size; } // 明示的実装 //それ以外は省略 } 以上が悩みの原因です。1は何となく大丈夫だと思います。配列がそうなので。 2と最後は、「もう絶対に仕様変更しない! これが完成形だ」というのであれば良いのでしょう。配列やinteger、色のように値のようなクラスなら仕様変更もそれ以外と比べて少ないでしょう。 そういうものなら良いのかもしれません。・・・・・・たぶん。 というのが、c#初心者上がりのjava初心者の見解です。 どなたか分かる方、いらっしゃいましたらご意見、アドバイスを頂きたいです。
回答: いまいち何を聞きたいのかわかりませんが・・・ 1. については大丈夫です。 final 変数が書き換えられないことはコンパイラが保証しています。 さすがに実行時にクラスファイルを書き換えられた場合とかは知りませんが、普通そんなことは有り得ないので大丈夫でしょう。 2. と 3. と 4. はほぼ同じことを言っていると思うのですが、 あなたの言っているとおり public final フィールドは仕様変更しないような場所で利用するのが望ましいでしょう。 これは java 言語の残念な点ですね。 この辺については scala などの新しい jvm 言語では上手く対応している(scalaでは引数なしのメソッド呼び出しは括弧を省略できる & フィールドアクセスは同名のメソッド呼び出し)ので、興味があったら使ってみると良いと思います。