在某些情况下,Java编译器不会抱怨默认方法引入的模棱两可的方法调用。为什么?

时间:2018-10-23 19:51:45

标签: java interface multiple-inheritance

注意:这是出于好奇而产生的问题。我玩得很开心,遇到了一种我无法完全解释的奇怪行为。我不是要解决任何实际问题,也不是多重继承的支持者。 ;-)

据我所知,在Java中,当一个类从不同的接口继承具有相同签名和返回类型的多个默认方法时,该类通常必须重写该方法并提供自己的实现以解决歧义(覆盖方法可以使用InterfaceName.super.foo()显式调用默认方法之一。例如,请参见here

但是,如果这些接口仅提供相同的默认方法,因为它们都扩展相同的超级接口,并且所有接口仅继承,则这是不正确的该超级接口的方法。这对于编译器来说很好。仅当其中某些接口使用自己的实现覆盖默认方法时,才会引入歧义(在这种情况下,编译器会抱怨)。

但是,如果仅一个接口覆盖了默认方法,则编译器会奇怪地不会抱怨。

例如,以下代码可以编译并正常运行:

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中的重写方法声明而没有检测到这种“隐藏”的歧义并表现出一些未定义的行为?任何规范的引用将是一个加号。 :)

0 个答案:

没有答案