覆盖抽象方法的默认方法实现

Default method implementation to override abstract method

Java-8 中不允许以下内容:

public interface Operator {
    default String call() throws Exception {
      // do some default things
      return performOperation();
    }

    String performOperation();
}

public abstract class AbstractTestClass {
    public abstract String call() throws Exception;
}

public class TestClass extends AbstractTestClass implements Operator {
    @Override
    public String performOperation() {
      // do some operation
    }
}

上面的编译失败,错误消息说 TestClass 需要抽象或重写调用方法。

我在想默认方法可以提供必要的覆盖。为什么那不起作用?

我被迫做如下事情:

public interface Operator {
    default String doCall() throws Exception {
      // do some default things
      return performOperation();
    }

    String performOperation();
}

public abstract class AbstractTestClass {
    public abstract String call() throws Exception;
}

public class TestClass extends AbstractTestClass implements Operator {
    String call() throws Exception {
      doCall();
    }

    @Override
    public String performOperation() {
      // do some operation
    }
}

这缺少我正在寻找的简洁设计。

我在问题中看到解决方案是:

public class TestClass extends AbstractTestClass implements Operator {
    String call() throws Exception {
      Operator.super.call();
    }

    @Override
    public String performOperation() {
      // do some operation
    }
}

但是,该解决方案并未解释为什么编译器不允许上述清洁设计。我想了解推理,看看是否有办法在 TestClass.

中隐藏 call 方法

见 JLS §8.4.8.4 Inheriting Methods with Override-Equivalent Signatures:

This exception to the strict default-abstract and default-default conflict rules is made when an abstract method is declared in a superclass: the assertion of abstract-ness coming from the superclass hierarchy essentially trumps the default method, making the default method act as if it were abstract. However, the abstract method from a class does not override the default method(s), because interfaces are still allowed to refine the signature of the abstract method coming from the class hierarchy.

您仍然可以使用该方法的默认实现,您只需显式调用它,使用 InterfaceName.super.methodName():

public class TestClass extends AbstractTestClass implements Operator {
    @Override
    public String call() throws Exception {
        return Operator.super.call();
    }
    @Override
    public String performOperation() {
        // do some operation
    }
}

哦,您的 performOperation() 方法缺少 public 关键字和 @Override 注释。