is not abstract and does not override の原因と直し方
抽象メソッドの実装漏れ。extendsとimplementsの使い分け、可視性の制約も扱います。
エラーメッセージの読み方
Main.java:4: error: Main is not abstract and does not override abstract method area() in Shape
Main.java- ファイル名
4- 行番号 — javacが異常に気づいた位置。原因の行とは限りません
error- 種別 — コンパイルエラー。実行まで到達しません
Main is not abstract and does not override abstract method area() in Shape- 内容 — javacが期待していたもの、または見つけられなかったもの
このエラーが出る典型パターン
パターン1
1 abstract class Shape { 2 abstract double area(); 3 } 4 public class Main extends Shape { 5 ^ 6 public static void main(String[] args) { 7 System.out.println(new Main().area()); 8 } 9 }
抽象メソッドは具象クラスで必ず実装します。実装しないならクラス自体もabstractにします。
直し方: (空) を double area() { return 1.0; } にします。
パターン2
1 interface Greeter { 2 void greet(); 3 } 4 public class Main extends Greeter { ^ 5 public void greet() { System.out.println("hi"); } 6 public static void main(String[] args) { 7 new Main().greet(); 8 } 9 }
クラスの継承はextends、インターフェースの実装はimplementsです。多重に実装できるのは後者だけです。
直し方: extends を implements にします。
パターン3
1 interface Greeter { 2 void greet(); 3 } 4 public class Main implements Greeter { 5 void greet() { System.out.println("hi"); } ^ 6 public static void main(String[] args) { 7 new Main().greet(); 8 } 9 }
インターフェースのメソッドは暗黙にpublicです。実装側でpublicを省くとパッケージ内限定になり狭まります。
直し方: (空) を public にします。
パターン4
1 abstract class Shape { 2 abstract double area(); 3 abstract double perimeter(); 4 } 5 public class Main extends Shape { 6 double area() { return 4.0; } 7 ^ 8 public static void main(String[] args) { 9 System.out.println(new Main().area()); 10 } 11 }
抽象メソッドは1つでも実装し忘れると、そのクラス全体が具象クラスとして認められません。
直し方: (空) を double perimeter() { return 8.0; } にします。
パターン5
1 import java.io.IOException; 2 abstract class Loader { 3 abstract void load() throws IOException; 4 } 5 public class Main extends Loader { 6 void load() throws Exception { } ^ 7 public static void main(String[] args) throws Exception { 8 new Main().load(); 9 } 10 }
オーバーライドでは親より広い検査例外を新たに投げることはできません。宣言する例外は親と同じか、より狭い範囲にします。
直し方: Exception を IOException にします。
よくある誤解
エラーは実装が漏れているクラス側に出ます。抽象メソッドを追加した親クラス側ではありません。
実務での勘所
このエラーが起きるのは、実装が必須の抽象メソッド(abstractメソッドや、defaultを付けていないインターフェースメソッド)を実装していない場合だけです。Java 8以降のインターフェースはdefaultメソッドを持てるようになり、defaultを付けたメソッドは実装クラス側でオーバーライドしなくてもコンパイルが通ります。「インターフェースのメソッドは全部実装が必須」という理解は、Java 7以前では正しくてもJava 8以降は正確ではありません。