作者:查建樺 | 来源:互联网 | 2022-12-01 15:51
注意:这是一个纯粹好奇的问题.我玩得很开心,我遇到了一个我无法完全解释的好奇行为.我不是要解决任何实际问题,也不是多重继承的支持者.;-)
据我所知,在Java中,当一个类从不同的接口继承多个具有相同签名和返回类型的默认方法时,该类通常必须重写该方法并提供自己的实现来解决歧义(覆盖方法可能是明确的)调用默认方法之一InterfaceName.super.foo()
).例如,见这里.
但是,如果这些接口仅提供相同的默认方法,因为它们都扩展了相同的超级接口,并且所有接口仅从该超级接口继承该默认方法,则情况并非如此.这对编译器来说很好.只有当其中一些接口使用自己的实现覆盖默认方法时才会引入歧义(在这种情况下,编译器会抱怨).
但是,如果只有一个接口覆盖了默认方法,编译器就会好奇地不抱怨.
例如,以下编译并运行正常:
interface Creature {
default void whoAmI() {
System.out.println("creature");
}
}
interface Horse extends Creature {
}
interface Human extends Creature {
@Override
default void whoAmI() {
System.out.println("human");
}
}
public class Centaur implements Horse, Human {
public static void main(String... args) {
new Centaur().whoAmI(); // prints 'human'
}
}
有趣的是human
,输出是,而不是creature
.(好吧,另一种方式也同样有趣.)我的猜测是编译器不允许这样做,因为方法调用是不明确的.
问:这是预期的行为吗?如果是,理由是什么?(我想有人可能会争辩说,如果只有一个接口覆盖了默认方法,那么应该优先考虑该覆盖).或者只是编译器以某种方式不检测这种"隐藏"歧义并通过将方法调用链接到接口中的重写方法声明来展示一些未定义的行为Human
?任何规范的引用都是有利的.:)