阴影接口的默认方法

Cod*_*roc 6 java java-8 default-method

考虑以下情况,

interface IFace1 {
    default void printHello() {
        System.out.println("IFace1");
    }
}

interface IFace2 {
    void printHello();
} 

public class Test implements IFace1, IFace2 {

    public static void main(String[] args) {
        Test test = new Test();
        test.printHello();

        IFace1 iface1 = new Test();
        iface1.printHello();

        IFace2 iface2 = new Test();
        iface2.printHello();
    }

    @Override
    public void printHello() {
        System.out.println("Test");
    }
}
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,我得到了非常期待的输出.

Test
Test
Test
Run Code Online (Sandbox Code Playgroud)

我一直在阅读有关Java-8默认方法的内容,特别是有关扩展包含默认方法的接口的内容

2 nd bullet:重新声明默认方法,使其成为抽象方法.

在上面的例子中,我有这有相同名称的默认方法两个接口,当我实现了这两个我才能够达到执行printHelloTest是指IFace2.

我对此几乎没有疑问,

  1. 我怎样才能到达printHello方法IFace1 如果我不能比,为什么?
  2. 没有这种行为从本质上意的让我走IFace1通过其他方法现在阴影?

引用说,你可以在它的子界面中制作default方法abstract.例如,

interface IFace2 extends IFace1 {
    void printHello();
}
Run Code Online (Sandbox Code Playgroud)

在这里,当我实现时,我IFace2实际上无法达到default方法,IFace1这正是我案例中发生的事情.

Hol*_*ger 7

看来你对default方法的存在感到有点困惑.所以,让我们忘记IFace1.printHello()一个default方法.那么,有一个明显的情况:Test实现两个接口,IFace1并且IFace2碰巧有一个具有相同名称和签名的方法.

Test实现该方法,从而实现两个接口的方法.default方法的新特性不会改变这种逻辑.此外,语言设计者注意添加default方法不会影响现有代码的行为,因此如果您的类实现了该方法,则方法的存在default变得无关紧要.

但是,如果您编写的代码知道方法的存在default,则可以调用它,如果它是由直接超级接口声明或继承的,即在您的代码中可以IFace1.super.printHello()用来调用default方法IFace1.

这些规则与超类规则没有太大区别.如果更改接口以使接口IFace2扩展IFace1并仍然声明printHello()abstract方法,则此abstract方法会覆盖该default方法,您无法再IFace1.super.printHello()从内部调用Test.

如上所述,这些规则与普通实例方法没有太大区别.如果Test声明了一个方法printHello(),那么这是您可以通过对实例的引用调用的唯一方法Test,无论其声明的类型是Test,IFace1还是IFace2.只有Test自身的实现方法可以进行super调用.


当涉及可能的接口多重继承时,主要区别就在起作用.如果你的类Test没有实施该方法printHello(),它取决于两个接口的继承关系,会发生什么

  • 如果是IFace2extends IFace1,那么它的抽象方法会重新声明该default方法,因此会发生编译器错误,因为Test必须实现该abstract方法
  • 如果IFace2没有扩展IFace1,则存在两个具有相同名称和签名的可继承方法,因此Test不会继承该default方法,并且会发生编译器错误,因为Test必须实现该abstract方法
  • 如果是IFace1extends IFace2,Test将继承该default方法.如果Test没有实现它也将继承它IFace2,但这应该是一个惊喜......


Sot*_*lis 5

我怎样才能到达 IFace1 的 printHello 方法,如果我不能,为什么?

你只能一个类型的实例方法内这样做实现IFace1

IFace1.super.printHello(); // only if IFace1 declares a default implementation of the method
Run Code Online (Sandbox Code Playgroud)

换句话说,您不能通过简单的类型IFace1Test(或其他)引用来做到这一点。那会破坏封装。

这种行为不会让我远离 IFace1 的预期性质,现在可能被其他方法遮蔽了吗?

这里没有阴影。您已经覆盖了该方法,因此调用了覆盖的方法。

关于你的第三个问题,你没有扩展任何接口,所以我没有看到相关性。

如果你真的有

interface IFace2 extends IFace1 {
    void printHello();
}
Run Code Online (Sandbox Code Playgroud)

public class Test implements IFace2 {
Run Code Online (Sandbox Code Playgroud)

那么您将无法访问该方法IFace1default实现。你永远不能跳过超类型来访问继承层次结构中更高的实现。

  • @TAsk _meaningful_ 是什么意思?如果您不在 `Test` 中覆盖它,您的代码将无法编译。 (3认同)
  • @TAsk:`new Test().printHello()` 将*总是* 调用`Test` 中声明的方法,无论你如何定义接口或`Test` 是否实现它们。 (2认同)