sealedメンバーをオーバーライドしようとした原因と直し方
sealed overrideを付けたメンバーを、さらに下の派生クラスでオーバーライドしようとすると出るコンパイルエラーです。
エラーメッセージの読み方
Program.cs(10,26): error CS0239: 'Puppy.Speak()': cannot override inherited member 'Dog.Speak()' because it is sealed
Program.cs- ファイル名
10- 行番号
26- 列番号 — この位置でコンパイラが解析に失敗しました
CS0239- エラーコード — 検索するとMicrosoftの解説ページが見つかります
'Puppy.Speak()': cannot override inherited member 'Dog.Speak()' because it is sealed- 内容 — 期待していたもの、または受け付けられなかったもの
このエラーが出る典型パターン
パターン1
1 class Animal { 2 public virtual void Speak() { System.Console.WriteLine("..."); } 3 public virtual void Move() { System.Console.WriteLine("..."); } 4 } 5 class Dog : Animal { 6 public sealed override void Speak() { System.Console.WriteLine("Woof"); } 7 public override void Move() { System.Console.WriteLine("Run"); } 8 } 9 class Puppy : Dog { 10 public override void Speak() { System.Console.WriteLine("Yip"); } ^ 11 } 12 class Program { 13 static void Main(string[] args) { 14 Puppy p = new Puppy(); 15 p.Speak(); 16 p.Move(); 17 } 18 }
Program.cs(10,26): error CS0239: 'Puppy.Speak()': cannot override inherited member 'Dog.Speak()' because it is sealed
sealed overrideを付けたメンバーは、それ以上のクラスで再オーバーライドできません。継承階層をそこで止める宣言です。
直し方: Speak を Move にします。
広告
広告スロット(未設定)
パターン2
1 class Vehicle { 2 public virtual void Accelerate() { System.Console.WriteLine("..."); } 3 public virtual void Brake() { System.Console.WriteLine("..."); } 4 } 5 class Car : Vehicle { 6 public sealed override void Accelerate() { System.Console.WriteLine("Vroom"); } 7 public override void Brake() { System.Console.WriteLine("Stop"); } 8 } 9 class SportsCar : Car { 10 public override void Accelerate() { System.Console.WriteLine("Fast"); } ^ 11 } 12 class Program { 13 static void Main(string[] args) { 14 SportsCar s = new SportsCar(); 15 s.Accelerate(); 16 s.Brake(); 17 } 18 }
Program.cs(10,26): error CS0239: 'SportsCar.Accelerate()': cannot override inherited member 'Car.Accelerate()' because it is sealed
Carが安全のためAccelerateの挙動を固定したいときにsealed overrideを使います。派生クラスはBrakeのような他のメンバーは引き続き上書きできます。
直し方: Accelerate を Brake にします。
パターン3
1 class Shape { 2 public virtual double Area() { return 0; } 3 public virtual string Name() { return "shape"; } 4 } 5 class Square : Shape { 6 public sealed override double Area() { return 4; } 7 public override string Name() { return "square"; } 8 } 9 class SpecialSquare : Square { 10 public override double Area() { return 9; } ^ 11 } 12 class Program { 13 static void Main(string[] args) { 14 SpecialSquare s = new SpecialSquare(); 15 System.Console.WriteLine(s.Area()); 16 System.Console.WriteLine(s.Name()); 17 } 18 }
Program.cs(10,28): error CS0239: 'SpecialSquare.Area()': cannot override inherited member 'Square.Area()' because it is sealed
戻り値の型が違っても、sealedになっているメンバー名を再オーバーライドしようとすれば同じエラーになります。
直し方: double Area() { return 9; } を string Name() { return "special"; } にします。
よくある誤解
sealedはクラス全体だけでなく、個々のメンバーにも付けられます。クラスは継承できても、そのメンバーだけはこれ以上変更できないようにする場面で使います。
まとめ
sealedメンバーをオーバーライドしようとした原因と直し方は上級でつまずきやすい項目です。上の3パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。