同じメソッドを持つクラスに 2 つのインターフェースを実装します。どのインターフェース メソッドがオーバーライドされますか? 質問する

同じメソッドを持つクラスに 2 つのインターフェースを実装します。どのインターフェース メソッドがオーバーライドされますか? 質問する

同じメソッド名とシグネチャを持つ 2 つのインターフェース。ただし、単一のクラスによって実装されている場合、コンパイラはどのメソッドがどのインターフェース用であるかをどのように識別するのでしょうか。

元:

interface A{
  int f();
}

interface B{
  int f();
}

class Test implements A, B{   
  public static void main(String... args) throws Exception{   

  }

  @Override
  public int f() {  // from which interface A or B
    return 0;
  }
}   

ベストアンサー1

型が 2 つのインターフェースを実装し、それぞれがinterface同一のシグネチャを持つメソッドを定義している場合、実質的にはメソッドは 1 つだけとなり、区別できません。たとえば、2 つのメソッドの戻り値の型が競合する場合、コンパイル エラーになります。これは、継承、メソッドのオーバーライド、非表示、および宣言の一般的なルールであり、継承された 2 つのinterfaceメソッド間だけでなく、interfaceスーパー メソッド間の競合class、またはジェネリックの型消去による競合にも適用されます。


互換性の例

次の例ではinterface Gift、 があり、present()にはメソッド (贈り物を贈るなど) があり、 にもメソッド(ゲストが欠席ではなく出席しているなど) がinterface Guestあります。present()

Presentable johnnyは a でありGift、 a でもありますGuest

public class InterfaceTest {
    interface Gift  { void present(); }
    interface Guest { void present(); }

    interface Presentable extends Gift, Guest { }

    public static void main(String[] args) {
        Presentable johnny = new Presentable() {
            @Override public void present() {
                System.out.println("Heeeereee's Johnny!!!");
            }
        };
        johnny.present();                     // "Heeeereee's Johnny!!!"

        ((Gift) johnny).present();            // "Heeeereee's Johnny!!!"
        ((Guest) johnny).present();           // "Heeeereee's Johnny!!!"

        Gift johnnyAsGift = (Gift) johnny;
        johnnyAsGift.present();               // "Heeeereee's Johnny!!!"

        Guest johnnyAsGuest = (Guest) johnny;
        johnnyAsGuest.present();              // "Heeeereee's Johnny!!!"
    }
}

上記のスニペットはコンパイルされ、実行されます。

必要なのは 1 つだけである ことに注意してください。これは、と が「-同等」であるためです (@Override Gift.present()Guest.present()@OverrideJLS8.4.2 の翻訳)。

したがって、には のjohnny 実装が 1 つだけあり、を として扱うか としてpresent()扱うかは関係なく、呼び出すメソッドは 1 つだけです。johnnyGiftGuest


非互換性の例

継承された 2 つのメソッドが同等ではない例を次に示します@Override

public class InterfaceTest {
    interface Gift  { void present(); }
    interface Guest { boolean present(); }

    interface Presentable extends Gift, Guest { } // DOES NOT COMPILE!!!
    // "types InterfaceTest.Guest and InterfaceTest.Gift are incompatible;
    //  both define present(), but with unrelated return types"
}

これは、 からメンバーを継承する場合は、interfaceメンバー宣言の一般的な規則に従う必要があることをさらに繰り返します。ここでは、 と が互換性のない戻り値の型で定義されていますGift。一方が で他方がです。と を1 つの型で使用できないのと同じ理由で、この例ではコンパイル エラーが発生します。Guestpresent()voidbooleanvoid present()boolean present()


まとめ

@Overrideメソッドのオーバーライドと非表示の通常の要件に従って、 - 同等のメソッドを継承できます。これらは - 同等である @Overrideため、実質的に実装するメソッドは 1 つだけであり、区別/選択するものはありません。

コンパイラは、どのメソッドがどのインターフェース用であるかを識別する必要はありません。なぜなら、それらが@Override同等であると判断されると、それらは同じメソッドになるからです。

潜在的な非互換性を解決するのは難しい作業かもしれませんが、それはまったく別の問題です。

参考文献

おすすめ記事