Java プログラマが C# を学ぶ際のメモ。final については探しても見当たらなかったので書いておきます。
定数・フィールドのfinal
定数に対しては const 識別子, コンストラクタ値を設定する書き込み禁止フィールドについては readonly 識別子を使います。
class Foo {
private const int NUM_MAX = 65535; // 定数値。コンストラクタでの遅延代入が不可。
private readonly int _id; // 書き込み禁止値。コンストラクタで遅延代入が可能。
<pre><code>public Foo(int id){
_id = id;
}
</code></pre>
}
メソッド中で、遅延代入をする方法はなさそうです。
public doSomething(){
readonly int j = 1; // これはエラー。readonly はフィールドでのみ可能。
const int N;
N = 10; // これもエラー。const は宣言と同時に代入しなければならない。
}
同様に、引数の final (引数の変数への再代入禁止)を C# で利用することはできません。
public void doSomeThing2(const int number); // const は引数には適用不可
クラスのfinal
クラスに対しては、sealed 識別子が同等の効果をもちます。
sealed class FinalClass{ /* … */ }
メソッドのfinal
Java におけるメソッドの宣言に対しての final は、C# ではデフォルトの実装のため、ポリモーフィズムについては C# のほうが Java より制限的といえます。
final でない(オーバーライド可能な)メソッドを定義するには、親で virtual 識別子をつけて宣言し、かつ子で override 識別子で明示してオーバーライドします。
override 識別子をつけている場合、さらにその子クラスでも再帰的にオーバーライドが可能です。オーバーライド可能なメソッドに対して「オーバーライドした上で子には禁止する」という動作を実装する場合は、クラスと同様に sealed 識別子を利用します。
class Parent {
public virtual void Greet(){ // オーバーライド可能
Console.WriteLine(“Hello”);
}
public void StandUp(){ // オーバーライド禁止。オーバーライドしようとするとコンパイルエラー
// …
}
}
class Child : Parent {
public override void Greet(){ // オーバーライド。明示しないとコンパイルエラー
Console.WriteLine(“Hi!!”);
}
}
class GrandChild : Child {
public sealed override void Greet(){ // オーバーライド。ただし、このクラスの子にはオーバーライドを許さない。
}
}
参考: