1. ホーム

[解決済み】同じメソッドを持つクラスで2つのインターフェースを実装する。どのインターフェイスのメソッドがオーバーライドされるか?

2022-04-02 21:47:55

質問

同じメソッド名とシグネチャを持つ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;
  }
}   

解決方法は?

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


互換性の例

以下は interface Gift があり、その中に present() メソッド(プレゼントを贈るという意味)と、さらに interface Guest も持っています。 present() メソッド(ゲストは存在し、不在ではない、という意味)を使用します。

Presentable johnnyGiftGuest .

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() は"です。 @Override -等価である。 JLS 8.4.2 ).

このように johnny は1つの実装しかありません。 present() をどのように扱うかは問題ではありません。 johnny として、または Gift または Guest の場合、呼び出すべきメソッドは1つだけです。


非互換性の例

以下は、2つの継承されたメソッドが NOT である場合の例です。 @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 は、メンバー宣言の一般規則に従わなければなりません。ここでは GiftGuest 定義 present() は、互換性のない戻り値の型があります。 void もう一方 boolean . というのは、同じ理由で void present()boolean present() が1つの型に含まれている場合、この例ではコンパイルエラーになります。


概要

というメソッドを継承することができます。 @Override -と同等です。ただし、メソッドのオーバーライドと隠蔽に関する通常の要件に従います。これらは ARE @Override -が等しい場合、事実上実装する方法は1つだけなので、区別・選択することはできません。

と判断されれば、コンパイラはどのメソッドがどのインターフェースに対応したものかを特定する必要はないのです。 @Override -等価であれば、同じメソッドです。

非互換性を解決するのは厄介な作業かもしれませんが、それは全く別の問題です。

参考文献