小编典典

用相同的方法在一个类中实现两个接口。哪个接口方法被覆盖?

all

具有相同方法名称和签名的两个接口。但是由单个类实现,那么编译器将如何识别哪个方法用于哪个接口?

前任:

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;
  }
}

阅读 111

收藏
2022-05-06

共1个答案

小编典典

如果一个类型实现了两个接口,并且每个接口都interface定义了一个签名相同的方法,那么实际上只有一个方法,并且它们是不可区分的。例如,如果这两个方法的返回类型冲突,那么这将是一个编译错误。这是继承、方法覆盖、隐藏和声明的一般规则,并且不仅适用于两个继承interface方法之间的可能冲突,也适用于一个interface和一个超级class方法之间的冲突,甚至只是由于泛型的类型擦除引起的冲突。


兼容性示例

这是一个示例,其中您有一个interface Gift,它有一个present()方法(例如,赠送礼物),还有一个interface Guest,它也有一个present()方法(例如,客人在场并且没有缺席)。

Presentable johnny既是 aGift又是 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!!!"
    }
}

上面的代码片段编译并运行。

请注意, 只有一个 @Override 必要!. 这是因为Gift.present()Guest.present()是“
-等价的@Override”(JLS
8.4.2
)。

因此,johnny 只有一个实现present()无论您如何对待johnny,无论是作为 aGift还是作为 a
Guest,都只有一种方法可以调用。


不兼容示例

这是一个示例,其中两个继承的方法不@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"
}

这进一步重申了从 an
继承成员interface必须遵守成员声明的一般规则。在这里,我们有GiftGuest定义present()了不兼容void的返回类型:一个另一个boolean。出于同样的原因,您不能在一个类型中使用void present()boolean present(),此示例会导致编译错误。


概括

您可以继承@Override等效的方法,但要符合方法覆盖和隐藏的通常要求。由于它们
@Override等效的,因此实际上只有一种方法可以实现,因此没有什么可区分/选择的。

编译器不必确定哪个方法适用于哪个接口,因为一旦确定它们是@Override等效的,它们就是相同的方法。

解决潜在的不兼容性可能是一项棘手的任务,但这完全是另一个问题。

参考

2022-05-06