7

考虑以下情况,

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");
    }
}

在上面的示例中,我得到以下输出,这是非常预期的。

Test
Test
Test

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

第二个项目符号:重新声明默认方法,使其抽象。

在上面的示例中,我有两个具有相同名称的默认方法的接口,当我实现这两个接口时,我只能访问其中引用printHello的实现。TestIFace2

我对此有几个问题,

  1. 我怎样才能达到printHello方法,IFace1 如果我不能比为什么?
  2. 这种行为不会让我远离预期的性质,IFace1现在可能会被其他方法所掩盖吗?

引用说,您可以在它的子界面中创建该default方法。例如,abstract

interface IFace2 extends IFace1 {
    void printHello();
}

在这里,当我实施时,我IFace2实际上无法达到default这种方法,IFace1这正是我的情况。

4

2 回答 2

7

似乎您对default方法的存在感到有些困惑。所以让我们暂时忘记这IFace1.printHello()是一种default方法。那么,有一个明确的情况:Test实现了两个接口,IFace1IFace2,它们恰好有一个名称和签名相同的方法。

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 IFace2Test将继承该default方法。Test如果不实现,它也会继承它IFace2,但这应该会让人感到意外……</li>
于 2015-09-10T18:15:42.427 回答
5

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

您只能在实现的类型的实例方法中这样IFace1

IFace1.super.printHello(); // only if IFace1 declares a default implementation of the method

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

这种行为是否让我远离 IFace1 的预期性质,现在可能被其他方法所掩盖?

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

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

如果你真的有

interface IFace2 extends IFace1 {
    void printHello();
}

public class Test implements IFace2 {

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

于 2015-09-10T17:56:48.167 回答