用同样的方法在一个类中实现两个接口。 哪个接口方法被覆盖?
两个接口具有相同的方法名称和签名。 但是由一个类实现,那么编译器将如何识别哪个接口是哪个方法?
例如:
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; } }
如果一个types实现了两个接口,并且每个interface
定义了一个具有相同签名的方法,那么实际上只有一个方法,并且它们是不可区分的。 如果说,这两种方法有冲突的返回types,那么这将是一个编译错误。 这是inheritance,方法重写,隐藏和声明的一般规则,也适用于不仅在2个inheritance的interface
方法之间,而且也在interface
和超class
方法之间的可能冲突,甚至仅适用于genericstypes擦除的冲突。
兼容性示例
下面是一个例子,其中有一个interface Gift
,它有一个present()
方法(如in,呈现礼物),还有一个interface Guest
,它也有一个present()
方法(如in,guest是存在的并且不存在)。
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()
是“ Guest.present()
”( JLS 8.4.2 )。
因此, johnny
只有一个 present()
实现 ,不pipe你如何对待johnny
,无论是作为Gift
还是作为Guest
,只有一个方法可以调用。
不兼容的例子
下面是两个inheritance的方法不是@Override
-equivalent的例子:
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
inheritance成员必须遵守成员声明的一般规则。 这里我们有Gift
和Guest
定义present()
与不兼容的返回types:一个void
另一个boolean
。 出于同样的原因,你不能在一个types中boolean present()
一个void present()
和一个boolean present()
,这个例子会导致编译错误。
概要
您可以inheritance@Override
-equivalent的方法,但要遵守方法覆盖和隐藏的通常要求。 由于它们是 @Override
-equivalent,所以实际上只有一种方法可以实现,因此没有任何区分/select。
编译器不需要确定哪个接口是哪个方法,因为一旦它们被确定为@Override
-equivalent,它们是相同的方法。
解决潜在的不兼容可能是一个棘手的任务,但这完全是另一个问题。
参考
- JLS 8.4.2方法签名
- JLS 8.4.8inheritance,重写和隐藏
- JLS 8.4.8.3覆盖和隐藏的要求
- JLS 8.4.8.4用Override-Equivalent签名inheritance方法
- “一个类可以通过覆盖等价签名来inheritance多个方法。”
就编译器而言,这两种方法是相同的。 两者都会有一个实现。
如果两种方法实际上是相同的,那么这不是问题,因为它们应该具有相同的实现。 如果它们在合同上有所不同(按照每个界面的文档),您将遇到麻烦。
这被标记为这个问题的重复https://stackoverflow.com/questions/24401064/understanding-and-solving-the-diamond-problems-in-java
你需要Java 8来获得多重inheritance的问题,但它仍然不是一个直接的问题。
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.
没有什么可以确定的。 接口只禁止方法名称和签名。 如果两个接口都有完全相同名称和签名的方法,则实现类可以使用单个具体方法来实现这两种接口方法。
但是,如果两种界面方法的语义契约是矛盾的,那么你几乎失去了; 那么你不能在一个类中实现两个接口。
尝试以匿名方式实现接口。
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(){ } }
在接口中,我们只是声明方法,实现这两个接口的具体类理解是只有一个方法(正如你所描述的,在返回types中都有相同的名字)。 所以不应该有一个问题,你可以在具体的类中定义该方法。
但是当两个接口有一个名字相同但返回types不同的方法时,在具体的类中实现了两个方法:
请看下面的代码:
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中查找并获取它。但是仍然给编译时错误,即返回types与InterfaceB的方法不兼容。
所以它对编译器来说是不合适的。
这样,你将无法实现两个接口有相同名称但返回types不同的方法。
那么如果他们都是一样的没关系。 它使用每个接口方法的一个具体方法来实现它们。