Java 为什么继承的默认方法不能像继承的类方法那样实现另一个接口?
我正在学习Java8,我遇到了一个使用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
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()
契约似乎是非常乐观的由于显式的成本太低,我们在这里错误地要求更具体。