首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何解决Java 8默认方法继承?

如何解决Java 8默认方法继承?
EN

Stack Overflow用户
提问于 2018-10-26 01:01:31
回答 2查看 0关注 0票数 0

设有以下类型:

代码语言:javascript
复制
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继承sayHi()Base,因为如果MyClass是仅实现Bar,则Base执行将被称为?因此,代码仍然无法编译是有意义的。另外,既然Bar应该Base执行sayHi(),为什么我不能MyClass像下面那样覆盖它:

代码语言:javascript
复制
@Override
public void sayHi() {
    Bar.super.sayHi();
}

尝试这样做时会发生以下错误:

错误类型限定符Bar默认超级调用方法,sayHi()在Foo中被覆盖

EN

回答 2

Stack Overflow用户

发布于 2018-10-26 09:29:21

JLS 9.4.1中几乎使用您的确切示例来指定此行为,只是更改了一些名称:

代码语言:javascript
复制
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从Top继承name(),但Bottom从Left继承name(),而不是Right。这是因为Left中的name()会覆盖Top中name()的声明。

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

票数 0
EN

Stack Overflow用户

发布于 2018-10-26 10:51:23

JLS 15.12.3开始

如果表单是TypeName。超级 [TypeArguments]标识符,然后:

  • 如果TypeName表示接口,则让T为紧邻方法调用的类型声明。如果存在一个与编译时声明不同的方法,则会从直接超类或直接超级接口覆盖(第9.4.1节)编译时声明,从而发生编译时错误。

在超级接口覆盖祖父表格接口中声明的方法的情况下,此规则通过简单地将祖父表添加到其直接超接口列表中来防止子接口“跳过”覆盖。访问祖父母的功能的适当方式是通过直接超级接口,并且仅当该接口选择暴露期望的行为时。(或者,开发人员可以自由定义他自己的附加超接口,通过超级方法调用公开所需的行为。)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/-100005102

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档