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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2801878/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 13:00:10  来源:igfitidea点击:

Implementing two interfaces in a class with same method. Which interface method is overridden?

javainterfaceoverriding

提问by Jothi

Two interfaces with same method names and signatures. But implemented by a single class then how the compiler will identify the which method is for which interface?

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

Ex:

前任:

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

采纳答案by polygenelubricants

If a type implements two interfaces, and each interfacedefine a method that has identical signature, then in effect there is only one method, and they are not distinguishable. If, say, the two methods have conflicting return types, then it will be a compilation error. This is the general rule of inheritance, method overriding, hiding, and declarations, and applies also to possible conflicts not only between 2 inherited interfacemethods, but also an interfaceand a super classmethod, or even just conflicts due to type erasure of generics.

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



Compatibility example

兼容性示例

Here's an example where you have an interface Gift, which has a present()method (as in, presenting gifts), and also an interface Guest, which also has a present()method (as in, the guest is present and not absent).

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

Presentable johnnyis both a Giftand a Guest.

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!!!"
    }
}

The above snippet compiles and runs.

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

Note that there is only one@Overridenecessary!!!. This is because Gift.present()and Guest.present()are "@Override-equivalent" (JLS 8.4.2).

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

Thus, johnnyonly has one implementationof present(), and it doesn't matter how you treat johnny, whether as a Giftor as a Guest, there is only one method to invoke.

因此,johnny只有一个执行present(),并不要紧,你如何对待johnny,无论是作为Gift或作为Guest,只有一个调用方法。



Incompatibility example

不兼容示例

Here's an example where the two inherited methods are NOT @Override-equivalent:

这是两个继承方法不@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"
}

This further reiterates that inheriting members from an interfacemust obey the general rule of member declarations. Here we have Giftand Guestdefine present()with incompatible return types: one voidthe other boolean. For the same reason that you can't an void present()and a boolean present()in one type, this example results in a compilation error.

这进一步重申了从 a 继承成员interface必须遵守成员声明的一般规则。下面我们就GiftGuest定义present()不兼容的返回类型:一个void其他的boolean。与不能在一种类型中使用anvoid present()和 a 的原因相同boolean present(),此示例会导致编译错误。



Summary

概括

You can inherit methods that are @Override-equivalent, subject to the usual requirements of method overriding and hiding. Since they ARE@Override-equivalent, effectively there is only one method to implement, and thus there's nothing to distinguish/select from.

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

The compiler does not have to identify which method is for which interface, because once they are determined to be @Override-equivalent, they're the same method.

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

Resolving potential incompatibilities may be a tricky task, but that's another issue altogether.

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

References

参考

回答by Paul Whelan

Well if they are both the same it doesn't matter. It implements both of them with a single concrete method per interface method.

好吧,如果它们都相同,那没关系。它使用每个接口方法的单个具体方法来实现它们。

回答by Ash

As far as the compiler is concerned, those two methods are identical. There will be one implementation of both.

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

This isn't a problem if the two methods are effectively identical, in that they should have the same implementation. If they are contractually different (as per the documentation for each interface), you'll be in trouble.

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

回答by Michael Borgwardt

There is nothing to identify. Interfaces only proscribe a method name and signature. If both interfaces have a method of exactly the same name and signature, the implementing class can implement both interface methods with a single concrete method.

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

However, if the semanticcontracts of the two interface method are contradicting, you've pretty much lost; you cannot implement both interfaces in a single class then.

但是,如果这两个接口方法的语义契约是矛盾的,那你就输了;那么你不能在一个类中实现两个接口。

回答by dcanh121

Try implementing the interface as anonymous.

尝试将接口实现为匿名。

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(){

}

}

回答by Bhagrav Jain

As in interface,we are just declaring methods,concrete class which implements these both interfaces understands is that there is only one method(as you described both have same name in return type). so there should not be an issue with it.You will be able to define that method in concrete class.

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

But when two interface have a method with the same name but different return type and you implement two methods in concrete class:

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

Please look at below code:

请看下面的代码:

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

when compiler gets method "public void print()" it first looks in InterfaceA and it gets it.But still it gives compile time error that return type is not compatible with method of InterfaceB.

当编译器获取方法“public void print()”时,它首先在 InterfaceA 中查找并获取它。但它仍然给出编译时错误,即返回类型与 InterfaceB 的方法不兼容。

So it goes haywire for compiler.

所以它对编译器来说是一团糟。

In this way, you will not be able to implement two interface having a method of same name but different return type.

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

回答by Peter Lawrey

This was marked as a duplicate to this question https://stackoverflow.com/questions/24401064/understanding-and-solving-the-diamond-problems-in-java

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

You need Java 8 to get a multiple inheritance problem, but it is still not a diamon problem as such.

你需要 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.

As JB Nizet comments you can fix this my overriding.

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

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

However, you don't have a problem with

但是,您没有问题

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.