扩展其他接口的默认方法和接口

Pau*_*ton 28 java java-8 default-method

假设有两个接口Interface1,Interface2其中Interface2扩展Interface1.

interface Interface1 {

    default void method() {
        System.out.println("1");
    }

    // Other methods
}

interface Interface2 extends Interface1 {

    @Override
    default void method() {
        System.out.println("2");
    }

    // Other methods
}
Run Code Online (Sandbox Code Playgroud)

假设我想创建一个实现的类,Interface2但我想method()成为其中的版本Interface1.如果我写

class MyClass implements Interface1, Interface2 {

    public void method() {
        Interface1.super.method();
    }
}
Run Code Online (Sandbox Code Playgroud)

我收到编译错误:

默认超级调用中的错误类型限定符:冗余接口Interface1由Interface2扩展

可以通过创建第三个界面来解决这个问题:

interface Interface3 extends Interface1 {

    default void method() {
        Interface1.super.method();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后:

class MyClass implements Interface1, Interface2, Interface3 {

    public void method() {
        Interface3.super.method();
    }
}
Run Code Online (Sandbox Code Playgroud)

这编译很好,如果我实例化一个新的MyClass和调用method(),输出是1预期的.

所以我的问题是,考虑到你可以只InterfaceName.super.method()针对链中最具体的界面编写限制,很容易绕过限制,限制的原因是什么?Interface1.super.method()首先禁止你写作会阻止哪些问题?

Rad*_*def 18

这正是JLS在15.12.3中 解决的问题."编译 - 时间步骤3:选择的方法是否合适?" .

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

  • [...]
  • 如果TypeName表示一个接口,那么让我们T直接包含方法调用的类型声明.如果存在一个与编译时声明不同的方法,则会从直接超类或直接超接口覆盖(第9.4.1节)编译时声明,从而发生编译时错误T.

JLS继续解释为什么规则到位:

在超级接口覆盖祖父节点接口中声明的方法的情况下,此规则通过简单地将祖父节点添加到其直接超接口列表中来防止子接口"跳过"覆盖.访问祖父母的功能的适当方式是通过直接超级接口,并且仅当该接口选择暴露期望的行为时.

因此,或多或少存在专门阻止你做你想做的事情.

但JLS似乎也承认你的解决方法:

(或者,开发人员可以自由定义自己的附加超接口,通过超级方法调用公开所需的行为.)

  • 我认为"他们没关系"是对这个评论的误读(主要是听到你想听的内容).一般来说,规则是有充分理由的(原因甚至在这里给出); 当编译器说"不要那样做"时,你的第一个想法不应该是"让我移除刀片防护并向最聪明的保姆状态显示".在这种情况下,不可能阻止用户在所有情况下做蠢事,但仍然不推荐,这并不意味着我们应该尽可能地放弃警告用户. (2认同)
  • @Radiodef公平评论.现实情况是:多重继承比单一继承更复杂,即使在通过禁止多重继承状态并选择聪明的冲突解决规则来躲避90%的复杂性之后.用户有20年的"继承/覆盖意味着什么"的经验,以单一继承为条件,当他们尝试将其应用于多重继承时,他们的直觉经常会失败.我们可以通过禁止真正有问题的位来使它更容易,但"更容易"和"容易"是不一样的. (2认同)
  • @BrianGoetz我明白了.因此,无论它是否有用,我们都有机会用我们熟悉的概念("意大利面条型")之外的特征射击自己,并且很难取消这种可能性.(并且在考虑之后,似乎不允许覆盖规避技巧的冲突解决方案往往更加严格而不是有用.)再次感谢您的时间. (2认同)