C# で Java の final と同等の制限をかける

Java プログラマが C# を学ぶ際のメモ。final については探しても見当たらなかったので書いておきます。

定数・フィールドのfinal

定数に対しては const 識別子, コンストラクタ値を設定する書き込み禁止フィールドについては readonly 識別子を使います。

[code]
class Foo {
private const int NUM_MAX = 65535; // 定数値。コンストラクタでの遅延代入が不可。
private readonly int _id; // 書き込み禁止値。コンストラクタで遅延代入が可能。

public Foo(int id){
    _id = id;
}

}
[/code]

メソッド中で、遅延代入をする方法はなさそうです。

[code]
public doSomething(){
readonly int j = 1; // これはエラー。readonly はフィールドでのみ可能。
const int N;
N = 10; // これもエラー。const は宣言と同時に代入しなければならない。
}
[/code]

同様に、引数の final (引数の変数への再代入禁止)を C# で利用することはできません。
[code]
public void doSomeThing2(const int number); // const は引数には適用不可
[/code]

クラスのfinal

クラスに対しては、sealed 識別子が同等の効果をもちます。
[code]
sealed class FinalClass{ /* … */ }
[/code]

メソッドのfinal

Java におけるメソッドの宣言に対しての final は、C# ではデフォルトの実装のため、ポリモーフィズムについては C# のほうが Java より制限的といえます。

final でない(オーバーライド可能な)メソッドを定義するには、親で virtual 識別子をつけて宣言し、かつ子で override 識別子で明示してオーバーライドします。

override 識別子をつけている場合、さらにその子クラスでも再帰的にオーバーライドが可能です。オーバーライド可能なメソッドに対して「オーバーライドした上で子には禁止する」という動作を実装する場合は、クラスと同様に sealed 識別子を利用します。

[code]
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(){ // オーバーライド。ただし、このクラスの子にはオーバーライドを許さない。
}
}

[/code]

参考: