Java8默认方法继承
假设有以下几种类型:Java8默认方法继承,java,interface,multiple-inheritance,Java,Interface,Multiple 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
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
应该有Base
的sayHi()
实现,为什么我不能在MyClass
中重写它呢
@Override
public void sayHi() {
Bar.super.sayHi();
}
尝试执行此操作时发生以下错误:
默认超级调用方法中的错误类型限定符栏,sayHi()在Foo中被重写
此行为是使用中几乎完全相同的示例指定的,只是更改了一些名称:
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 {}
右侧从顶部继承name(),而底部从左侧继承name(),
不对。这是因为左侧的name()覆盖了声明
名称()的名称在顶部
JLS似乎没有给出我能看到的任何特别具体的理由;这正是Java设计人员决定继承工作的方式。这是设计的结果。发件人:
如果表单是TypeName。超级的。[TypeArguments]标识符,然后:
- 如果TypeName表示接口,则T是立即包含方法调用的类型声明。如果存在不同于编译时声明的方法,该方法从T的直接超类或直接超接口重写()编译时声明,则会发生编译时错误
@凯西,你在用什么IDE?Eclipse给出了另一个错误。@jornverne来自IntelliJ。Eclipse输出了什么?@Casey
非法引用了类型Base中的超级方法sayHi(),无法绕过类型Foo中更具体的重写
Eclipse的消息显然更清楚。只是尝试从命令行编译,并在默认的超级调用Bar.super.sayHi()中获取错误类型限定符Bar;方法sayHi()在Java 1.8.0的Foo
中被重写_45@Casey我有1.8.0μ91,也许差别就在那里。有道理。有点像是设计上的缺陷。覆盖默认方法将永远隐藏原始实现,这在复杂的层次结构中可能非常关键。似乎让具体类决定使用哪个实现会是一个更好的主意。@aiguy这是…某种程度上的覆盖点。对于普通的类继承来说总是这样,覆盖会完全隐藏超类型实现。好吧,在普通的类继承中,你永远不会有两个父实现。我的观点是,如果在一个复杂的层次结构中,有人添加了对原始默认实现的覆盖,那么如果某些具体类依赖于原始实现,它可能会破坏整个层次结构。@aiguy如果具体类依赖于原始实现,那么它们就做错了。@aiguy很好,这一个回答了你提出的一个实际问题。另一个回答了一个你实际上没有提出的隐含问题,所以我想这一个应该会赢。但是,凯西比路易斯更需要代表(对不起,路易斯),所以还是接受另一个吧