JDK 8 中的默认值是 Java 中多重继承的一种形式吗?
Posted
技术标签:
【中文标题】JDK 8 中的默认值是 Java 中多重继承的一种形式吗?【英文标题】:Are defaults in JDK 8 a form of multiple inheritance in Java? 【发布时间】:2011-12-13 01:22:31 【问题描述】:JDK 8 中的一项新功能允许您在保留二进制兼容性的同时添加到现有接口。
语法是这样的
public interface SomeInterface()
void existingInterface();
void newInterface() default SomeClass.defaultImplementation;
对于SomeInterface
的所有现有实现,当他们升级到这个新版本时,它们不会突然在newInterface()
周围出现编译错误。
虽然这很简洁,但是当您实现两个接口时会发生什么,这两个接口都添加了一个您没有实现的新默认方法?让我用一个例子来解释。
public interface Attendance
boolean present() default DefaultAttendance.present;
public interface Timeline
boolean present() default DefaultTimeline.present;
public class TimeTravelingStudent implements Attendance, Timeline
// which code gets called?
new TimeTravelingStudent().present();
这是否已被定义为 JDK 8 的一部分?
我发现 Java 大神在这里 http://cs.oswego.edu/pipermail/lambda-lib/2011-February/000068.html 谈论类似的东西,但它是私人邮件列表的一部分,我不能直接问他们。
有关如何在 JDK 8 中使用默认值以及扩展 Collection 接口以支持 lambdas 的更多详细信息,请参阅此处: https://oracleus.wingateweb.com/published/oracleus2011/sessions/25066/25066_Cho223662.pdf
【问题讨论】:
要观看的视频会话在这里medianetwork.oracle.com/video/player/1113272518001 这是设计师谈论称为虚拟扩展的功能。他还谈到了这不会破坏向后兼容性。 所以我的例子的答案是目前你得到一个编译器错误。但他们对其他解决方案持开放态度。 另一个有用的材料是cr.openjdk.java.net/~briangoetz/lambda/… 旁注:接口方法的默认实现的最终语法被证明是不同的(代码块而不是对外部类的引用)。 Java 一直都有类型的多重继承。默认方法添加 behavior 的多重继承,但不添加 state 的多重继承。 (在 C++ 等语言中,状态的多重继承是最麻烦的地方。) 【参考方案1】:重复操作的答案是:
要解决多重继承问题,实现两个接口的类为相同的方法名称和签名提供默认实现,必须提供该方法的实现。 [Full Article]
我对你的问题的回答是:是的,它是多重继承的一种形式,因为你可以继承不同父母的行为。缺少的是继承状态,即。例如,属性。
【讨论】:
+1:当发生冲突时,它将采用更具体的实现而不是不太具体的实现,允许您指定在发生冲突时应该是哪一个。 @H-Man2 我不明白。如果这是真的,则意味着它将破坏二进制兼容性。现在,这可能还好于破坏二进制兼容性以防止多重继承,破坏二进制兼容性很糟糕。 @PeterLawrey 在我的示例中哪一个更具体? @Pyrolistical:不,它不会破坏兼容性,因为编译器可以将默认实现转换为正常的方法调用。我认为它更像是一个宏而不是真正的继承,但可以模拟 mul.-inheritance 的各个方面。也许彼得的视频提供了更详细的答案。 实际上我们可以通过抽象的getter和setter来解决缺失的状态,实现类可以添加状态...【参考方案2】:我知道这是一篇旧帖子,但因为我正在处理这些东西......
编译器会报错,告诉你:
类 TimeTravelingStudent 从类型出勤和时间线继承不相关的 present() 默认值 对 present 的引用不明确,Timeline 中的 present() 方法和出勤中的 present() 方法都匹配。
【讨论】:
【参考方案3】:有两种场景:
1) 首先,上面提到过,没有最具体的界面
public interface A
default void doStuff() /* implementation */
public interface B
default void doStuff() /* implementation */
public class C implements A, B
// option 1: own implementation
// OR
// option 2: use new syntax to call specific interface or face compilation error
void doStuff()
B.super.doStuff();
2) 第二,当有更具体的界面时:
public interface A
default void doStuff() /* implementation */
public interface B extends A
default void doStuff() /* implementation */
public class C implements A, B
// will use method from B, as it is "closer" to C
【讨论】:
【参考方案4】:简而言之:这是一个编译时错误,必须在实现中手动覆盖该方法。
默认方法的目的
在 Java 8 中引入默认方法的主要目的是在不破坏现有实现的情况下使接口可扩展(有很多 3rd 方 Java 库)。
而像 C++ 中的 multiple inheritance
实际上是为了避免使用,这绝对不是 Java 中默认方法的目的。
如何覆盖
2 个选项:
用自己的逻辑覆盖方法。 重写方法,通过super
调用接口的方法之一,格式:<interface_name>.super.<method_name>();
提示:
接口中的方法默认为public,所以在覆盖时不要忘记添加public
关键字。
【讨论】:
【参考方案5】:我对你的问题的回答是:是的,它是多重继承的一种形式,因为你可以继承不同父母的行为。缺少的是继承状态,即。例如,属性。
是的,但是您可以将 getter 和 setter 添加到实现类然后必须实现的接口。然而,实现类不继承属性。所以,AFAICS,它更像是一个特质风格的解决方案,而不是一个多重继承风格的解决方案。
【讨论】:
【参考方案6】:如果有人仍在寻找答案,如果一个类使用相同的默认方法实现了两个接口,那么该类需要通过提供自己的实现来解决歧义。查看this 教程,了解有关默认方法中的继承如何工作的更多详细信息。
【讨论】:
【参考方案7】:“我们将如何区分方法”是放在 *** 上的一个问题,并提到了这个问题concrete methods in interfaces Java1.8
以下是应该回答该问题的示例:
interface A
default public void m()
System.out.println("Interface A: m()");
interface B
default public void m()
System.out.println("Interface B: m()");
class C implements A,B
public void m()
System.out.println("Concrete C: m()");
public static void main(String[] args)
C aC = new C();
aC.m();
new A().m();
new B().m();
上面的C类必须实现自己的接口A和B的具体方法。即:
public void m()
System.out.println("Interface C: m()");
要从特定接口调用方法的具体实现,您可以实例化 >接口并显式调用该接口的具体方法
例如,以下代码从接口A调用具体方法m()的实现:
new A().m();
上面的输出是:
接口 A:m()
【讨论】:
【参考方案8】:在我看来,它不是多重继承,因为它们是无状态的。 所以虚拟扩展方法不支持完整的对象或类功能。
【讨论】:
以上是关于JDK 8 中的默认值是 Java 中多重继承的一种形式吗?的主要内容,如果未能解决你的问题,请参考以下文章