Java 8个默认方法继承

Java 8 default method inheritance

假设有以下类型:

public interface Base {

    default void sayHi(){
        System.out.println("hi from base");
    }
}

public interface Foo extends Base {
    @Override
    default void sayHi(){
        System.out.println("hi from foo");
    }
}

public interface Bar extends Base {
}

public class MyClass implements Foo, Bar {
    public static void main(String[] args) {
        MyClass c = new MyClass();
        c.sayHi();
    }
}

在这种情况下,如果执行main,则打印"hi from foo"。为什么 Foo 的实现优先? Bar 不会从 Base 继承 sayHi(),因为如果 MyClass 只实现 Bar,那么会调用 Base 实现?因此,代码仍然无法编译是有意义的。此外,由于 Bar 应该有 BasesayHi() 的实现,为什么我不能在 MyClass 中覆盖它,例如:

@Override
public void sayHi() {
    Bar.super.sayHi();
}

尝试这样做时出现以下错误:

bad type qualifier Bar in default super call method, sayHi() is overridden in Foo

此行为是使用几乎与您在 JLS 9.4.1 中完全相同的示例指定的,只是更改了一些名称:

interface Top {
    default String name() { return "unnamed"; }
}
interface Left extends Top {
    default String name() { return getClass().getName(); }
}
interface Right extends Top {}

interface Bottom extends Left, Right {}

Right inherits name() from Top, but Bottom inherits name() from Left, not Right. This is because name() from Left overrides the declaration of name() in Top.

JLS 似乎没有给出任何我能看到的特别具体的原因;这就是 Java 设计者决定继承的方式。

这是设计使然。来自 JLS 15.12.3:

If the form is TypeName . super . [TypeArguments] Identifier, then:

  • If TypeName denotes an interface, let T be the type declaration immediately enclosing the method invocation. A compile-time error occurs if there exists a method, distinct from the compile-time declaration, that overrides (§9.4.1) the compile-time declaration from a direct superclass or direct superinterface of T.

In the case that a superinterface overrides a method declared in a grandparent interface, this rule prevents the child interface from "skipping" the override by simply adding the grandparent to its list of direct superinterfaces. The appropriate way to access functionality of a grandparent is through the direct superinterface, and only if that interface chooses to expose the desired behavior. (Alternately, the developer is free to define his own additional superinterface that exposes the desired behavior with a super method invocation.)