【问题标题】:Java 8 doesn't provide the same solution to allow multiple inheritance which they gave to solve interface default methodsJava 8 没有提供与解决接口默认方法相同的解决方案来允许多重继承
【发布时间】:2023-03-22 03:06:02
【问题描述】:

问题:

我们知道 Java 不允许扩展多个类,因为它会导致 Diamond Problem 编译器无法决定使用哪个超类方法。在Java 8 中引入了接口默认方法钻石问题。也就是说,如果一个类实现了两个接口,每个接口都定义了相同的默认方法,并且实现类没有覆盖公共默认方法,编译器无法决定选择哪个实现。

解决方案:

Java 8 需要为多个接口实现的默认方法提供一个实现。因此,如果一个类同时实现了上面提到的两个接口,它就必须为通用默认方法提供一个实现。否则编译器会抛出编译时错误。

问题:

为什么这个解决方案不适用于多类继承,通过覆盖子类引入的常用方法?

【问题讨论】:

    标签: java-8 multiple-inheritance default-method


    【解决方案1】:

    接口引入的方法可能总是被覆盖,而类引入的方法可能是最终的。这就是为什么您可能无法对类应用与对接口相同的策略的原因之一。

    【讨论】:

      【解决方案2】:

      您没有正确理解钻石问题(当然,维基百科文章的当前状态没有充分解释它)。如图所示,

      同一个类通过不同的继承路径被多次继承时,就会出现菱形问题。这对接口来说不是问题(从来没有),因为它们只定义一个合约,多次指定同一个合约没有区别。

      主要问题与方法无关,而与该超类型的 数据 相关。在这种情况下,A 的实例状态应该存在一次还是两次?如果有一次,CB 可能对 A 的实例状态有不同的、冲突的约束。这两个类也可能假设完全控制A 的状态,即不考虑其他类具有相同的访问级别。如果有两个不同的A 状态,则将D 引用扩大到A 引用就会变得模棱两可,因为A 可能意味着。

      接口没有这些问题,因为它们根本不携带实例数据。他们也(几乎)没有可访问性问题,因为他们的方法总是public。允许default 方法并不会改变这一点,因为default 方法仍然不访问实例变量,而是仅使用接口方法进行操作。

      当然,BC 声明 default 方法具有相同的签名,这可能会导致必须在 D 中解决的歧义。但即使没有A,即根本没有“钻石”,情况也是如此。所以这个场景不是“钻石问题”的正确例子。

      【讨论】:

      • 我同意菱形问题的共享状态的论点,但同样,如果您在 Java 中支持多重继承,您将不得不处理选择单个方法的多个实现之一的问题。问题中说明了这个问题以及如何解决 Java 8 中的接口。不能保证将相同的解决方案应用于类。还是我错过了什么?
      • @Harmlezz:如上一段所述,必须在多个继承的非abstract 方法之间消除歧义的问题通常是多重继承的问题,但它不需要公共因此,要显示的超类型与 Diamond 问题无关。你是对的,对于非interface 类来说,这是一个无法以同样方式解决的问题,但仍然不是所谓的“钻石问题”。
      【解决方案3】:

      描述为“钻石问题”的冲突最好通过对方法A.m() 的多态调用来说明,其中接收者的运行时类型为D:想象D 继承了两种不同的方法,它们都声称要播放A.m() 的角色(其中之一可以是原始方法A.m(),至少其中之一是覆盖)。现在,动态调度无法决定调用哪个冲突方法。

      除此之外:“钻石问题”和常规名称冲突之间的区别在 Eiffel 等语言中尤为重要,其中冲突可以在本地D 类型的角度解决 ,例如,通过重命名一种方法。这将避免静态类型 D 的调用的名称冲突,但不会避免静态类型 A 的调用。

      现在,使用 Java 8 中的默认方法,JLS 被修改为检测任何此类冲突的规则,需要D 来解决冲突(存在许多不同的情况,取决于所涉及的某些类型是否是类) .也就是说,钻石问题在 Java 8 中没有“解决”,只是通过拒绝任何会产生它的程序来避免它。

      理论上,类似的规则可以在 Java 1 中定义以允许类的多重继承。这只是早期做出的决定,Java 的设计者不想要支持多重继承。

      允许默认方法而不是类方法的多重(实现)继承的选择纯粹是务实的选择,任何理论都没有必要。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-04-08
        • 2012-08-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-20
        • 2015-12-04
        相关资源
        最近更新 更多