简体   繁体   English

带接口的多重继承歧义

[英]Multiple Inheritance Ambiguity with Interface

We all know about the diamond problem regarding multiple inheritance - 我们都知道有关多重遗传的钻石问题 -

   A
  / \
 B   C
  \ / 
   D

This problem describe an ambiguous situation for class D . 这个问题描述了D类的模糊情况。 If class A has a method and both/either of B and/or C override the method then which version of method does D override? 如果A类有一个方法并且B和/或C两个/都覆盖了该方法,则D覆盖哪个版本的方法?

Is this problem also applicable for interfaces in Java? 这个问题是否也适用于Java中的接口? If not, how do Java interfaces overcome this problem? 如果没有,Java接口如何克服这个问题?

The diamond problem only applies to implementation inheritance ( extends in all versions of Java prior to Java 8). 菱形问题仅适用于实现继承(在Java 8之前的所有Java版本中都有extends )。 It doesn't apply to API inheritance ( implements in all versions of Java prior to Java 8). 它不适用于API继承(在Java 8之前的所有Java版本中implements )。

Since interface methods with matching type signatures are compatible, there is no diamond problem if you inherit the same method signature twice: matching method signatures simply coalesce instead. 由于具有匹配类型签名的接口方法是兼容的,因此如果您继承两次相同的方法签名,则不存在菱形问题:匹配方法签名只是简单地合并。 (And if the type signatures aren't the same, then you don't have the diamond problem either.) (如果类型签名不一样,那么你也没有钻石问题。)

In Java 7 and below, the only way to inherit implementation code was via the extends keyword, which restricts to at most one parent. 在Java 7及更低版本中,继承实现代码的唯一方法是使用extends关键字,该关键字最多只能限制一个父级。 Therefore there is no multiple implementation inheritance and the diamond problem does not exist. 因此,没有多重实现继承,并且钻石问题不存在。

Java 8 adds a new wrinkle because it allows interfaces to have implementation code. Java 8增加了一个新的皱纹,因为它允许接口具有实现代码。 It still escapes the diamond problem by simply falling back to the previous behavior (no implementation inheritance) when you're implementing multiple interfaces with methods that have matching signatures. 当您使用具有匹配签名的方法实现多个接口时,它仍然可以通过简单地回退到先前的行为(没有实现继承)来逃避钻石问题。

To add to existing answers about Java8 multiple inheritance with interfaces (aka how Java still avoids the diamond problem): 通过接口添加有关Java8多重继承的现有答案(也就是Java如何仍然避免钻石问题):

There are three rules to follow: 有三条规则要遵循:

  1. A class always wins . 班级总是胜利 Class's own method implementation takes priority over default methods in Interfaces. 类自己的方法实现优先于接口中的默认方法。

  2. If class doesn't have any: the most specific interface wins 如果类没有: 最具体的接口获胜

在此输入图像描述

  1. If above is not the case, inheriting class has to explicitly state which method implementation it's using (otherwise it won't compile) 如果不是这种情况,继承类必须显式声明它正在使用哪个方法实现(否则它将无法编译)

在此输入图像描述

Java overcomes this problem even though interfaces can have default implementations of methods, because the default implementation is either unambiguous (the one in class A ) or the situation is solved by some rule (when class B or class C overrides the implementation from class A , see below). Java克服了这个问题,即使接口可以有方法的默认实现,因为默认实现是明确的A类中A )或者情境是由某些规则解决的 (当B类或C类覆盖A类的实现时,见下文)。

When the supertypes of a class or interface provide multiple default methods with the same signature: 当类或接口的超类型提供具有相同签名的多个默认方法时:

  • Instance methods are preferred over interface default methods. 实例方法优于接口默认方法。
  • Methods that are already overridden by other candidates are ignored. 已忽略其他候选项的方法将被忽略。 This circumstance can arise when supertypes share a common ancestor . 当超类型共享一个共同的祖先时,就会出现这种情况

However, if two or more independently defined default methods conflict , or a default method conflicts with an abstract method, then the Java compiler produces a compiler error. 但是, 如果两个或多个独立定义的默认方法冲突 ,或者默认方法与抽象方法冲突,则Java编译器会产生编译器错误。 You must explicitly override the supertype methods . 必须显式覆盖超类型方法 In this case you could invoke any of the of the default implementations with the super keyword. 在这种情况下,您可以使用super关键字调用任何默认实现。

See also: How does Java 8' new default interface model works (incl. diamond, multiple inheritance, and precedence)? 另请参阅: Java 8的新默认接口模型如何工作(包括菱形,多重继承和优先级)?

With default methods in interface introduced in Java 8, multiple inheritance related problem may arise, there are 3 scenarios - 使用Java 8中引入的接口中的默认方法,可能会出现多个继承相关的问题,有3种情况 -

1- If implementing class overrides the default method and provides its own functionality for the default method then the method of the class takes priority over the interface default methods. 1-如果实现类重写默认方法并为默认方法提供自己的功能,则类的方法优先于接口默认方法。

2-When class implements both interfaces and both have the same default method, also the class is not overriding that method then the error will be thrown. 2 - 当类实现两个接口并且两者都具有相同的默认方法时,类也不会覆盖该方法,然后将抛出错误。

3-In case when an interface extends another interface and both have the same default method, the inheriting interface default method will take precedence. 3 - 如果接口扩展另一个接口并且两者都具有相同的默认方法,则继承接口缺省方法优先。

read more about it here . 在这里阅读更多相关信息。

Java doesn't support multiple inheritance, so the diamond problem doesn't arise. Java不支持多重继承,因此不会出现钻石问题。 If B & C are interfaces, then there is no implementation in the interfaces. 如果B&C是接口,则接口中没有实现。 Even if B & C override the method in interface A (cannot be a class), the methods will have same signature. 即使B&C覆盖接口A中的方法(不能是类),方法也会有相同的签名。 There is no ambiguity regarding which implementation to use, because there is no implementation. 关于使用哪种实现没有歧义,因为没有实现。

具有虚拟声明的接口,它们将没有实现,因此没有歧义问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM