Code Fix

上級

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を付けたメンバーは、それ以上のクラスで再オーバーライドできません。継承階層をそこで止める宣言です。

直し方: SpeakMove にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン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のような他のメンバーは引き続き上書きできます。

直し方: AccelerateBrake にします。

この問題を解いてみる →

パターン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パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)