的Java 8默认方法继承
比方说,有以下几种类型:的Java 8默认方法继承
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
被执行,“从富喜”被打印出来。为什么Foo
的实施优先? Bar
从Base
继承sayHi()
,因为如果MyClass
仅用于执行Bar
,那么将调用Base
实现?所以代码仍然不能编译是有意义的。此外,由于Bar
应有的Base
实施sayHi()
,为什么我不能覆盖它在MyClass
,如:
@Override
public void sayHi() {
Bar.super.sayHi();
}
试图这样做时,会出现以下错误:
坏类型修饰符在缺省超级调用方法中,sayHi()在Foo中被覆盖
这个行为几乎用你的确切示例在JLS 9.4.1中指定,只是wi TH一些名字各地更改:
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 {}
右(左起) 不是正继承名()的顶部,但底部继承名()。这是因为来自Left的name()覆盖了Top()中name()的声明 。
JLS似乎没有给出任何特别具体的理由,我可以看到;这正是Java设计者决定如何继承的原因。
这是设计。从JLS 15.12.3:
如果表单是TypeName。超级。 [TypeArguments]标识符,然后:
- 如果类型名表示接口,设T为直接封闭方法调用中的类型声明。如果存在一个方法中,从编译时声明不同,重写(§9.4.1)从一个直接超类或T.
的直接超接口在这种情况下的编译时声明发生编译时间错误超级接口覆盖在祖父接口中声明的方法,该规则通过简单地将祖父母添加到其直接超级接口列表中来防止子接口“跳过”覆盖。访问祖父母功能的适当方式是通过直接超级接口,并且只有当该接口选择暴露所需的行为。 (另外,开发人员可以*定义暴露了超级方法调用所需的行为他自己额外的高级接口。)
在这和[其他答案](http://*.com/a/37197609/5221149)之间,问题已被全部解答。现在,哪个答案被接受?嗯.... – Andreas
@Casey什么IDE您使用的? Eclipse给出了另一个错误。 –
@JornVernee这是来自IntelliJ。 Eclipse输出了什么? – Casey
@Casey'''非法引用来自类型Base的超级方法sayHi(),无法绕过来自类型Foo''的更具体的覆盖。 –