Code Fix

上級

@Override が通らないときの確認手順

名前・引数・可視性の3点が一致条件です。オーバーロードとの違いを実例で確認します。

エラーメッセージの読み方

Main.java:5: error: method does not override or implement a method from a supertype
Main.java
ファイル名
5
行番号 — javacが異常に気づいた位置。原因の行とは限りません
error
種別 — コンパイルエラー。実行まで到達しません
method does not override or implement a method from a supertype
内容 — javacが期待していたもの、または見つけられなかったもの

このエラーが出る典型パターン

パターン1

 1  class Animal {
 2      void speak() { System.out.println("..."); }
 3  }
 4  public class Main extends Animal {
 5      @Override
 6      void Speak() { System.out.println("Hello"); }
               ^
 7      public static void main(String[] args) {
 8          new Main().speak();
 9      }
10  }
Main.java:5: error: method does not override or implement a method from a supertype

@Overrideは名前と引数が完全一致しないと通りません。この注釈がタイプミスを検出してくれます。

直し方: Speak を speak にします。

この問題を解いてみる →

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

パターン2

 1  class Base {
 2      void run(String s) { System.out.println("base"); }
 3  }
 4  public class Main extends Base {
 5      @Override
 6      void run(Object       s) { System.out.println("main"); }
                       ^
 7      public static void main(String[] args) {
 8          new Main().run("x");
 9      }
10  }
Main.java:5: error: method does not override or implement a method from a supertype

引数の型が違うとオーバーライドではなくオーバーロードになります。別のメソッドとして扱われます。

直し方: Object を String にします。

この問題を解いてみる →

パターン3

 1  class Base {
 2      protected void run() {}
 3  }
 4  public class Main extends Base {
 5      @Override
 6      private void run() {}
           ^
 7      public static void main(String[] args) {
 8          new Main().run();
 9      }
10  }
Main.java:6: error: run() in Main cannot override run() in Base attempting to assign weaker access privileges; was protected

オーバーライドで可視性を狭めることはできません。同じか、より広くする必要があります。

直し方: private を public にします。

この問題を解いてみる →

パターン4

 1  class Base {
 2      void handle(int n) { System.out.println("base"); }
 3  }
 4  public class Main extends Base {
 5      @Override
 6      void handle(Integer n) { System.out.println("main"); }
                       ^
 7      public static void main(String[] args) {
 8          new Main().handle(5);
 9      }
10  }
Main.java:5: error: method does not override or implement a method from a supertype

intとIntegerは別の型です。オートボクシングで自動変換されても、オーバーライドの型一致には使えません。

直し方: Integer を int にします。

この問題を解いてみる →

パターン5

 1  class Base {
 2      Object get() { return "x"; }
 3  }
 4  public class Main extends Base {
 5      @Override
 6      int      get() { return 1; }
            ^
 7      public static void main(String[] args) {
 8          System.out.println(new Main().get());
 9      }
10  }
Main.java:6: error: get() in Main cannot override get() in Base

戻り値の型はObjectのサブタイプなら変更できます(共変戻り値)。ただしintのようなプリミティブ型はObjectのサブタイプではないため使えません。

直し方: int を Integer にします。

この問題を解いてみる →

よくある誤解

@Overrideは必須ではありませんが、付けないとタイプミスが黙って通ります。オーバーライドのつもりが新しいメソッドになります。

実務での勘所

戻り値の型は、オーバーライドする側とされる側で完全に一致させる必要はありません。Java 5以降は共変戻り値型(covariant return type)が認められており、親クラスがAnimalを返すメソッドを、子クラスの実装ではより具体的なDog(Animalのサブクラス)を返すようにオーバーライドできます。@Overrideが通らないとき、名前や引数は合っているのに戻り値の型で失敗している場合は、戻り値がサブクラスの関係になっているかを確認してください。

演習をはじめる

関連するエラー

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