【问题标题】:Why an inherited default-method cannot implement another interface like an inherited class method? [duplicate]为什么继承的默认方法不能像继承的类方法那样实现另一个接口? [复制]
【发布时间】:2016-10-20 20:06:03
【问题描述】:

我正在学习 Java 8,我遇到了一个使用 default 方法的行为,我无法完全理解。

首先,一个“老式”的 Java sn-p 可以完美编译和运行:

abstract class A {
    public void print() {
        System.out.println("A");
    }
}
interface B {
    void print(); // implicitly public and abstract
}
class C extends A implements B {
    public void useInheritedPrint() {
      print(); // prints A
    }
}

CA 继承了一个已实现的print(),从B 继承了一个抽象的print(),这被认为是正确实现的。

但是如果A变成interfacedefault方法print(),如下:

interface A { 
    default void print() { // implicitly public
        System.out.println("A");
    }
}
interface B {
    void print(); // implicitly public and abstract
}
class C implements A,B {
    public void useInheritedPrint() {
      print(); // should print A
    }
}

即使C 仍然从A 继承print(),编译器仍会抱怨C 不是abstract(如果A 是如前所示的类,则不会发生同样的事情) .如果C 变成abstract 如下:

abstract class C implements A, B {
  public void useInheritedPrint() {
    print();
  }
}

然后编译器抱怨C 继承了default(来自A)和abstract print()(来自B)。

解决方案是在C 中定义一个abstract print(),如下:

class C implements A,B {
    public void useInheritedPrint() {
      print(); // should print A
    }
    public abstract void print(); // shall be implemented by a concrete subclass
}

或者覆盖print(),如:

class C implements A,B {
    public void useInheritedPrint() {
      print(); // should print A
    }
    public void print() { 
      // do something
    }
}

有谁知道在从 interface 继承 default method 和从父类继承它之间是否存在这种不对称行为的特殊原因?

这里是否涉及到致命的死亡钻石(我不明白为什么)?

【问题讨论】:

    标签: java inheritance java-8 overriding default-method


    【解决方案1】:

    你需要在C中实现print()

    class C implements A,B {
        public void useInheritedPrint() {
          print(); // should print A
        }
    
        @Override
        public void print() {
            A.super.print();
        }
    }
    

    基本原理是,如果您继承了两个具有相同签名的可能冲突的方法,则需要显式实现该方法并选择其中一个实现(或定义一个新实现)。

    【讨论】:

    • 我知道我需要,我问为什么。
    • 因为语言设计者选择这样设计它,可能是为了避免在没有意识到的情况下意外继承实现。
    • 我不同意,只有当它们都是默认的(=带有主体)并且在这种情况下 Java 强制实现它们的类覆盖时,您才能拥有具有相同签名的两个可能冲突的方法该方法(否则它不会编译)。但我的情况似乎并非如此,因为两者之一,B 的 print() 是抽象的,因此不可能发生冲突。
    • 我们只能推测。规则可能不同,规则可能更简单,或更复杂,或者其他什么,但它就是这样,你不能改变它。
    • @1d0m3n30 您正在使用“冲突”的乐观狭义定义。是的,这两个方法具有相同的签名——但是实现一个接口也意味着实现它的规范。由于在此处(A)声明print() 行为的类不知道B 对print() 的规范,因此假设A.print() 将满足C 中B.print() 的约定似乎非常乐观(第一个两者结合的地方。)由于明确的成本如此之低,因此我们错误地要求在这里要求更多的具体性。
    猜你喜欢
    • 2022-11-18
    • 1970-01-01
    • 1970-01-01
    • 2021-09-12
    • 1970-01-01
    • 2021-11-30
    • 2016-05-29
    • 2019-01-02
    • 1970-01-01
    相关资源
    最近更新 更多