java - 为什么 Java 不允许多重继承,但允许遵循具有默认实现的多个接口(interface)

标签 java inheritance interface java-8 abstract

我不是在问这个 -> Why is there no multiple inheritance in Java, but implementing multiple interfaces is allowed?

在 Java 中,不允许多重继承,但在 Java 8 之后,接口(interface)可以有默认方法(可以自己实现方法),就像抽象类一样。在这种情况下,它也应该允许多重继承。

interface TestInterface 
{ 
    // abstract method 
    public void square(int a); 

    // default method 
    default void show() 
    { 
      System.out.println("Default Method Executed"); 
    } 
} 

最佳答案

事情没那么简单。
如果一个类实现了多个定义了具有相同签名的默认方法的接口(interface),编译器将强制您为该类覆盖此方法。

以这两个接口(interface)为例:

public interface Foo {
    default void doThat() {
        // ...
    }
}

public interface Bar {    
    default void doThat() {
        // ...
    }       
}

它不会编译:

public class FooBar implements Foo, Bar{
}

您应该定义/覆盖该方法以消除歧义。
例如,您可以委托(delegate)给 Bar 实现,例如:

public class FooBar implements Foo, Bar{    
    @Override
    public void doThat() {
        Bar.super.doThat();
    }    
}

或委托(delegate)给 Foo 实现,例如: :

public class FooBar implements Foo, Bar {
    @Override
    public void doThat() {
        Foo.super.doThat();
    }
}

或仍然定义另一种行为:

public class FooBar implements Foo, Bar {
    @Override
    public void doThat() {
        // ... 
    }
}

该约束表明,即使对于接口(interface)默认方法,Java 也不允许多重继承。


我认为我们不能对多重继承应用相同的逻辑,因为可能会出现多重问题,主要是:

  • 如果继承类在内部依赖此方法,则覆盖/删除两个继承类中方法的歧义可能会引入副作用并改变继承类的整体行为。对于默认接口(interface),这种风险也存在,但它应该少得多,因为默认方法并非旨在引入复杂的处理,例如类内部的多个内部调用或有状态(实际上接口(interface)不能托管实例字段)。
  • 如何继承多个字段?即使语言允许,您也会遇到与之前引用的完全相同的问题:继承类行为的副作用:A 中定义的 int foo 字段> 和 B 要子类化的类没有相同的含义和意图。

关于java - 为什么 Java 不允许多重继承,但允许遵循具有默认实现的多个接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52620936/

相关文章:

java - Tomcat 8 如何设置jarsToSkip

c# - 如果我的类不继承任何东西,为什么我能够覆盖 Equals 方法?

javascript - 当 ob1.prototype 未定义时,Object.create() 如何从 ob1.prototype 创建 obj2.__proto__ ?

c# - 您如何平衡框架/API 设计和 TDD

c++ - 模板接口(interface)实现类 C++ 错误

JAVA实现接口(interface)

java - activemq jndi tomcat错误

java - 为什么我没有获得 hystrix 指标?

java - 结构查找和替换 IntelliJ

C++ 动态对象。运行时如何确定对象大小?