Java 为什么继承的默认方法不能像继承的类方法那样实现另一个接口?

Java 为什么继承的默认方法不能像继承的类方法那样实现另一个接口?,java,inheritance,java-8,overriding,default-method,Java,Inheritance,Java 8,Overriding,Default Method,我正在学习Java8,我遇到了一个使用default方法的行为,我不能完全理解 首先,是一个“老派”Java代码段,它可以完美地编译和运行: abstract class A { public void print() { System.out.println("A"); } } interface B { void print(); // implicitly public and abstract } class C extends A impleme

我正在学习Java8,我遇到了一个使用
default
方法的行为,我不能完全理解

首先,是一个“老派”Java代码段,它可以完美地编译和运行:

abstract class A {
    public void print() {
        System.out.println("A");
    }
}
interface B {
    void print(); // implicitly public and abstract
}
class C extends A implements B {
    public void useInheritedPrint() {
      print(); // prints A
    }
}
C
A
继承一个已实现的
print()
,从
B
继承一个被认为已正确实现的摘要
print()

但是如果
A
变成了
接口
,带有
默认值
方法
print()
,如下所示:

interface A { 
    default void print() { // implicitly public
        System.out.println("A");
    }
}
interface B {
    void print(); // implicitly public and abstract
}
class C implements A,B {
    public void useInheritedPrint() {
      print(); // should print A
    }
}
即使
C
仍然从
A
继承
print()
,编译器仍抱怨
C
不是
抽象的
(如果
A
是前面所示的类,则不会发生同样的情况)。如果
C
变成
abstract
,如下所示:

abstract class C implements A, B {
  public void useInheritedPrint() {
    print();
  }
}
然后编译器抱怨
C
继承了
默认值(来自
a
)和
摘要(来自
B

解决方案是在
C
中定义
abstract print()
,如下所示:

class C implements A,B {
    public void useInheritedPrint() {
      print(); // should print A
    }
    public abstract void print(); // shall be implemented by a concrete subclass
}
class C implements A,B {
    public void useInheritedPrint() {
      print(); // should print A
    }
    public void print() { 
      // do something
    }
}
或覆盖
print()
,如下所示:

class C implements A,B {
    public void useInheritedPrint() {
      print(); // should print A
    }
    public abstract void print(); // shall be implemented by a concrete subclass
}
class C implements A,B {
    public void useInheritedPrint() {
      print(); // should print A
    }
    public void print() { 
      // do something
    }
}
有人知道从
接口继承
默认方法
和从父类继承它之间的这种不对称行为是否有特殊原因吗


这里是否涉及致命的死亡钻石(我不明白为什么)?

您需要在C中实现
print()

class C implements A,B {
    public void useInheritedPrint() {
      print(); // should print A
    }

    @Override
    public void print() {
        A.super.print();
    }
}

其基本原理是,如果您继承了两个具有相同签名的可能冲突的方法,则需要显式实现该方法并选择其中一个实现(或定义一个新的实现)。

我知道我需要这样做,我问了为什么。因为语言设计者选择这样设计它,可能是为了避免在没有意识到的情况下意外继承一个实现。我不同意,只有当两个方法都是默认的(=带有一个主体),并且在这种情况下,Java强制实现它们的类重写该方法(否则它不会编译)时,才可以使用具有相同签名的两个可能冲突的方法。但我的情况似乎不是这样,因为其中一个,B的print()是抽象的,因此不可能有冲突。我们只能猜测。规则可以是不同的,规则可以更简单,或更复杂,或其他什么,但它是什么,你不能改变它。@1d0m3n30你使用的是一个乐观狭隘的“冲突”定义。是的,这两个方法具有相同的签名-但是实现接口意味着也要实现其规范。由于在这里(A)声明
print()
行为的类没有意识到B对
print()
的规范,因此假设
A.print()
将满足C中的
B.print()
契约似乎是非常乐观的由于显式的成本太低,我们在这里错误地要求更具体。