Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/313.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.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
Java 隐藏接口的默认方法_Java_Java 8_Default Method - Fatal编程技术网

Java 隐藏接口的默认方法

Java 隐藏接口的默认方法,java,java-8,default-method,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) {

考虑以下情况

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
default方法的书,特别是关于

第二项:重新声明默认方法,使其抽象化

在上面的示例中,我有两个具有相同名称的默认方法的接口,当我实现这两个接口时,我只能实现
Test
printHello
,它指的是
IFace2

我对此没有什么问题

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

  • 引用中说,您可以在它的子界面中设置
    默认
    方法
    抽象
    。比如说,

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

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

    只能在使用实现
    IFace1
    的类型的实例方法中执行此操作

    IFace1.super.printHello(); // only if IFace1 declares a default implementation of the method
    
    换句话说,您不能通过类型为
    IFace1
    Test
    (或其他)的简单引用来实现。这将破坏封装

    这种行为难道没有让我远离IFace1的预期性质吗 哪一个现在可能会被其他方法遮蔽

    这里没有阴影。您已经重写了该方法,因此将调用被重写的方法

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

    如果你真的有

    interface IFace2 extends IFace1 {
        void printHello();
    }
    


    然后您将无法访问该方法的
    IFace1
    default
    实现。您永远不能跳过超级类型来访问继承层次结构中更高层次的实现。

    您似乎对默认方法的存在感到有点困惑。让我们暂时忘记
    IFace1.printHello()
    是一种
    默认方法。因此,有一个明显的情况:
    Test
    实现了两个接口,
    IFace1
    IFace2
    ,它们恰好有一个具有相同名称和签名的方法

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

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

    这些规则与超类的规则没有太大区别。如果更改接口,使接口
    IFace2
    扩展
    IFace1
    ,并且仍然将
    printHello()
    声明为
    abstract
    方法,则此
    abstract
    方法会覆盖
    默认
    方法,并且无法调用
    IFace1.super.printHello()
    测试中开始

    如上所述,这些规则与普通实例方法没有太大区别。如果
    Test
    声明了一个方法
    printHello()
    ,那么无论其声明的类型是
    Test
    IFace1
    还是
    IFace2
    ,都只能通过引用
    Test
    实例来调用该方法。只有
    Test
    本身的实现方法才能执行
    super
    调用


    当涉及接口的可能多重继承时,主要的区别就开始发挥作用。如果您的类
    Test
    没有实现方法
    printHello()
    ,它取决于两个接口的继承关系,会发生什么情况

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

    @TAsk:
    new Test()。printHello()
    将始终调用
    Test
    中声明的方法,无论您如何定义接口或
    Test
    是否实现它们。@TAsk我不理解您的困惑。为什么您希望调用重写方法以外的任何东西?@TAsk您所说的有意义是什么意思?如果不在
    测试中重写它,代码将无法编译。
    
    interface IFace2 extends IFace1 {
        void printHello();
    }
    
    public class Test implements IFace2 {