does not implement inherited abstract member の原因と直し方
abstractなメンバーを持つ基底クラスを継承したのに、そのメンバーをoverrideしていないと出るコンパイルエラーです。
エラーメッセージの読み方
Program.cs(4,7): error CS0534: 'Circle' does not implement inherited abstract member 'Shape.Area()'
Program.cs- ファイル名
4- 行番号
7- 列番号 — この位置でコンパイラが解析に失敗しました
CS0534- エラーコード — 検索するとMicrosoftの解説ページが見つかります
'Circle' does not implement inherited abstract member 'Shape.Area()'- 内容 — 期待していたもの、または受け付けられなかったもの
このエラーが出る典型パターン
パターン1
1 abstract class Shape { 2 public abstract double Area(); 3 } 4 class Circle : Shape { 5 public double Radius; 6 ^ 7 } 8 class Program { 9 static void Main(string[] args) { 10 Circle c = new Circle { Radius = 2 }; 11 System.Console.WriteLine(c.Area()); 12 } 13 }
abstractなメンバーは、派生クラスで必ずoverrideして実装しなければなりません。1つでも忘れるとそのクラスはインスタンス化できません。
直し方: (空) を public override double Area() { return 3.14 * Radius * Radius; } にします。
パターン2
1 abstract class Vehicle { 2 public abstract void Drive(); 3 } 4 class Car : Vehicle { 5 ^ 6 } 7 class Program { 8 static void Main(string[] args) { 9 Car c = new Car(); 10 c.Drive(); 11 } 12 }
publicかoverrideのどちらかが欠けても、抽象メンバーの実装としては認められません。
直し方: (空) を public override void Drive() { System.Console.WriteLine("Driving"); } にします。
パターン3
1 abstract class Employee { 2 public abstract decimal CalculatePay(); 3 } 4 class Manager : Employee { 5 ^ 6 } 7 class Program { 8 static void Main(string[] args) { 9 Manager m = new Manager(); 10 System.Console.WriteLine(m.CalculatePay()); 11 } 12 }
戻り値の型(ここではdecimal)も基底クラスの宣言と完全に一致させる必要があります。
直し方: (空) を public override decimal CalculatePay() { return 5000; } にします。
パターン4
1 abstract class Shape { 2 public abstract double Perimeter(); 3 } 4 class Rectangle : Shape { 5 public double Width; 6 public double Height; 7 ^ 8 } 9 class Program { 10 static void Main(string[] args) { 11 Rectangle r = new Rectangle { Width = 3, Height = 4 }; 12 System.Console.WriteLine(r.Perimeter()); 13 } 14 }
abstractなメンバーはoverrideキーワードを付けて実装しないと、派生クラスをインスタンス化できません。
直し方: (空) を public override double Perimeter() { return 2 * (Width + Height); } にします。
パターン5
1 abstract class Task { 2 public abstract bool IsDone(); 3 } 4 class Chore : Task { 5 public bool Done; 6 ^ 7 } 8 class Program { 9 static void Main(string[] args) { 10 Chore c = new Chore { Done = true }; 11 System.Console.WriteLine(c.IsDone()); 12 } 13 }
戻り値の型(ここではbool)も基底クラスの宣言と一致させる必要があります。
直し方: (空) を public override bool IsDone() { return Done; } にします。
よくある誤解
interface-not-implementedと似ていますが、こちらはabstract classの話です。publicとoverrideの両方が揃って初めて「実装した」とみなされます。
実務での勘所
abstract classとinterfaceの使い分けの目安は、共有したいものが「状態(フィールド)や共通のロジック」を含むかどうかです。abstract classは、抽象メソッドと並行して、全ての派生クラスに共通するフィールドやコンストラクタ、すでに実装済みの通常のメソッドを持てます。派生クラスは抽象メンバーだけを実装すればよく、共通部分は継承するだけで手に入ります。純粋な「この操作ができることを保証する」という契約だけを表したいならinterface、共通の実装や状態も一緒に配りたいならabstract classを選びます。