带接口的多重继承歧义

时间:2015-04-20 20:54:34

标签: java oop inheritance interface diamond-problem

我们都知道有关多重继承的diamond problem -

   A
  / \
 B   C
  \ / 
   D

此问题描述了类D的模糊情况。如果类A有一个方法,并且B和/或C中的任何一个都覆盖了该方法,则D覆盖哪个版本的方法?

此问题是否也适用于Java中的接口?如果没有,Java接口如何克服这个问题?

6 个答案:

答案 0 :(得分:17)

菱形问题仅适用于Java 8之前的所有Java版本中的实现继承(extends)。它不适用于Java 8之前的所有Java版本中的 API 继承(implements)。

由于具有匹配类型签名的接口方法是兼容的,因此如果您继承两次相同的方法签名,则不存在菱形问题:匹配方法签名只是简单地合并。 (如果类型签名不相同,那么你也没有钻石问题。)

在Java 7及更低版本中,继承实现代码的唯一方法是使用extends关键字,该关键字最多只限制一个父级。因此,没有多重实现继承,并且钻石问题不存在。

Java 8增加了一个新的皱纹,因为它允许接口具有实现代码。当您使用具有匹配签名的方法实现多个接口时,它仍然可以通过简单地回退到先前的行为(没有实现继承)来逃避钻石问题。

答案 1 :(得分:5)

使用接口添加有关Java8多重继承的现有答案(a.k.a.Java仍然避免钻石问题):

要遵循三条规则:

  1. 课程总是胜利。类的自身方法实现优先于接口中的默认方法。

  2. 如果上课没有:最具体的界面获胜

  3. enter image description here

    1. 如果不是这种情况,继承类必须明确声明它使用哪种方法实现(否则它不会编译)
    2. enter image description here

答案 2 :(得分:3)

Java克服了这个问题,即使接口可以有方法的默认实现,因为默认实现是明确(类A中的那个)或情况得到解决通过某种规则(当班级B或班级C覆盖班级A的实施时,请参见下文)。

当类或接口的超类型提供多个具有相同签名的默认方法时:

  • 实例方法优于接口默认方法。
  • 忽略已被其他候选项覆盖的方法。 当超类型共享一个共同的祖先时,就会出现这种情况。

但是,如果两个或多个独立定义的默认方法冲突,或者默认方法与抽象方法冲突,则Java编译器会产生编译器错误。您必须显式覆盖超类型方法。在这种情况下,您可以使用super关键字调用任何默认实现。

另请参阅:How does Java 8' new default interface model works (incl. diamond, multiple inheritance, and precedence)?

答案 3 :(得分:3)

使用Java 8中引入的接口中的默认方法,可能会出现多个继承相关的问题,有3种情况 -

1-如果实现类重写默认方法并为默认方法提供自己的功能,则类的方法优先于接口默认方法。

2 - 当类实现两个接口并且两者都具有相同的默认方法时,类也不会覆盖该方法,然后将抛出错误。

3 - 如果接口扩展另一个接口并且两者都具有相同的默认方法,则继承接口的默认方法优先。

详细了解here

答案 4 :(得分:2)

Java不支持多重继承,因此钻石问题不会出现。如果B& C是接口,接口中没有实现。即使B& C覆盖接口A中的方法(不能是类),方法将具有相同的签名。关于使用哪种实现没有歧义,因为没有实现。

答案 5 :(得分:0)

具有伪声明的接口,它们将没有实现,因此没有 模棱两可的问题。