同じメソッド名とシグネチャを持つ 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()
@Override
JLS8.4.2 の翻訳)。
したがって、には のjohnny
実装が 1 つだけあり、を として扱うか としてpresent()
扱うかは関係なく、呼び出すメソッドは 1 つだけです。johnny
Gift
Guest
非互換性の例
継承された 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 つの型で使用できないのと同じ理由で、この例ではコンパイル エラーが発生します。Guest
present()
void
boolean
void present()
boolean present()
まとめ
@Override
メソッドのオーバーライドと非表示の通常の要件に従って、 - 同等のメソッドを継承できます。これらは - 同等である @Override
ため、実質的に実装するメソッドは 1 つだけであり、区別/選択するものはありません。
コンパイラは、どのメソッドがどのインターフェース用であるかを識別する必要はありません。なぜなら、それらが@Override
同等であると判断されると、それらは同じメソッドになるからです。
潜在的な非互換性を解決するのは難しい作業かもしれませんが、それはまったく別の問題です。
参考文献
- JLS 8.4.2 メソッドシグネチャ
- JLS 8.4.8 継承、オーバーライド、および非表示
- JLS 8.4.8.3 オーバーライドと非表示の要件
- JLS 8.4.8.4 オーバーライド同等のシグネチャを持つメソッドの継承
- 「クラスは、オーバーライドと同等のシグネチャを持つ複数のメソッドを継承することが可能です。」