Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java8默认方法继承_Java_Interface_Multiple Inheritance - Fatal编程技术网

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的直接超类或直接超接口重写()编译时声明,则会发生编译时错误
如果superinterface重写了在祖辈接口中声明的方法,则此规则通过简单地将祖辈接口添加到其直接superinterface列表中来防止子接口“跳过”重写。访问祖父母功能的适当方式是通过直接超级接口,并且只有当该接口选择公开所需的行为时。(或者,开发人员可以自由定义自己的附加超级接口,通过超级方法调用公开所需的行为。)


@凯西,你在用什么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很好,这一个回答了你提出的一个实际问题。另一个回答了一个你实际上没有提出的隐含问题,所以我想这一个应该会赢。但是,凯西比路易斯更需要代表(对不起,路易斯),所以还是接受另一个吧