使用相同的方法在一个类中实现两个接口。重写了哪个接口方法?

新手上路,请多包涵

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

前任:

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

原文由 Jothi 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 523
2 个回答

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


兼容性示例

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

Presentable johnny 既是 Gift 又是 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 )。

Thus, johnny only has one implementation of present() , and it doesn’t matter how you treat johnny , whether as a Gift or作为 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"
}

这进一步重申,从 interface 继承成员必须遵守成员声明的一般规则。 Here we have Gift and Guest define present() with incompatible return types: one void the other boolean .出于同样的原因,您不能在一种类型中使用 void present()boolean present() ,此示例会导致编译错误。


概括

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

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

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

参考

原文由 polygenelubricants 发布,翻译遵循 CC BY-SA 2.5 许可协议

这被标记为这个问题的重复 https://stackoverflow.com/questions/24401064/understanding-and-solving-the-diamond-problems-in-java

您需要 Java 8 才能解决多重继承问题,但它本身仍然不是钻石问题。

 interface A {
    default void hi() { System.out.println("A"); }
}

interface B {
    default void hi() { System.out.println("B"); }
}

class AB implements A, B { // won't compile
}

new AB().hi(); // won't compile.

正如 JB Nizet 评论的那样,您可以解决这个问题。

 class AB implements A, B {
    public void hi() { A.super.hi(); }
}

但是,您没有问题

interface D extends A { }

interface E extends A { }

interface F extends A {
    default void hi() { System.out.println("F"); }
}

class DE implement D, E { }

new DE().hi(); // prints A

class DEF implement D, E, F { }

new DEF().hi(); // prints F as it is closer in the heirarchy than A.

原文由 Peter Lawrey 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题