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

Java 使用相同的方法在一个类中实现两个接口。覆盖了哪个接口方法?,java,interface,overriding,Java,Interface,Overriding,具有相同方法名称和签名的两个接口。但是由单个类实现,那么编译器将如何识别哪个方法用于哪个接口 例: 如果它们都是一样的,那也没关系。它使用每个接口方法的一个具体方法来实现这两个方法 就编译器而言,这两种方法是相同的。两者都将有一个实现 如果这两种方法实际上是相同的,那么这不是问题,因为它们应该具有相同的实现。如果它们在合同上有所不同(根据每个接口的文档),您将遇到麻烦。没有什么可识别的。接口只禁止方法名和签名。如果两个接口都有一个名称和签名完全相同的方法,那么实现类可以用一个具体方法实现两个接口

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

例:


如果它们都是一样的,那也没关系。它使用每个接口方法的一个具体方法来实现这两个方法

就编译器而言,这两种方法是相同的。两者都将有一个实现


如果这两种方法实际上是相同的,那么这不是问题,因为它们应该具有相同的实现。如果它们在合同上有所不同(根据每个接口的文档),您将遇到麻烦。

没有什么可识别的。接口只禁止方法名和签名。如果两个接口都有一个名称和签名完全相同的方法,那么实现类可以用一个具体方法实现两个接口方法


然而,如果两个接口方法的语义契约是矛盾的,那么您几乎已经丢失了;那么,您不能在一个类中实现两个接口。

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


兼容性示例 下面是一个示例,其中您有一个
接口礼物
,它有一个
present()
方法(例如,赠送礼物),还有一个
接口来宾
,它也有一个
present()
方法(例如,来宾在场而不是缺席)

体面的约翰尼
既是
礼物
又是
客人

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!!!"
    }
}
上面的代码段编译并运行

请注意,只有一个
@覆盖
是必需的。这是因为
Gift.present()
Guest.present()
是“
@Override
-等价物”()

因此,
johnny
只有一个
present()
的实现,无论您如何对待
johnny
,无论是作为
礼物还是作为
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"
}
这进一步重申了从
接口继承成员必须遵守成员声明的一般规则。这里我们有
Gift
Guest
定义
present()
返回类型不兼容:一个
void
另一个
boolean
。与不能在一种类型中使用
void present()
boolean present()
的原因相同,此示例会导致编译错误


总结 您可以继承与
@Override
-等效的方法,这取决于方法重写和隐藏的通常要求。由于它们是
@Override
-等价的,实际上只有一种方法可以实现,因此没有什么可区分/选择的

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

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

工具书类
    • “一个类可以继承多个具有重写等效签名的方法。”

尝试将接口实现为匿名

public class MyClass extends MySuperClass implements MyInterface{

MyInterface myInterface = new MyInterface(){

/* Overrided method from interface */
@override
public void method1(){

}

};

/* Overrided method from superclass*/
@override
public void method1(){

}

}

和在接口中一样,我们只是声明方法,实现这两个接口的具体类理解为只有一个方法(正如您所描述的,两个方法在返回类型中具有相同的名称)。所以它不应该有问题,你们可以在具体的类中定义这个方法

但当两个接口有一个名称相同但返回类型不同的方法,并且您在具体类中实现了两个方法时:

请看下面的代码:

public interface InterfaceA {
  public void print();
}


public interface InterfaceB {
  public int print();
}

public class ClassAB implements InterfaceA, InterfaceB {
  public void print()
  {
    System.out.println("Inside InterfaceA");
  }
  public int print()
  {
    System.out.println("Inside InterfaceB");
    return 5;
  }
}
当编译器得到方法“public void print()”时,它首先在InterfaceA中查找并得到它。但它仍然给出编译时错误,返回类型和InterfaceB的方法不兼容

因此,编译器会陷入混乱


这样,您将无法实现具有相同名称但不同返回类型的方法的两个接口。

这被标记为此问题的重复项

您需要Java8来解决多重继承问题,但它本身仍然不是diamon问题

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.

它解释了为什么Java不允许扩展多个class@ArthurRonald实际上,它只是看起来有关联。然而,IMO这个扩展了多个类的类可能会遇到Diamond问题(在最派生的类中是重复的对象状态),这很可能就是Java让用户摆脱麻烦的原因。另一方面,实现多个类的类永远不会遇到菱形问题,因为接口不向对象提供状态。这个问题纯粹是由于语法限制——无法完全限定函数调用。谢谢——这很有帮助。然而,我有一个关于不兼容性的进一步问题,我作为一个BTW发布了这个问题,在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.