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

ari*_*rin 5 java default interface

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
    }
}
Run Code Online (Sandbox Code Playgroud)

上面的错误消息无法编译,说明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
    }
}
Run Code Online (Sandbox Code Playgroud)

这缺乏我正在寻找的干净设计.

我在这个问题中看到了解决方案:

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

    @Override
    public String performOperation() {
      // do some operation
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,该解决方案无法解释为什么编译器不允许上述干净的设计.我想理解推理,并且,看看是否有一种方法可以隐藏call方法TestClass.

And*_*eas 5

请参阅JLS§8.4.8.4使用覆盖等效签名继承方法:

abstract在超类中声明方法时,会对严格的default-abstract和default-default冲突规则进行此异常:来自超类层次结构的abstract-ness断言基本上胜过默认方法,使默认方法就像它一样是的abstract.但是,abstract类中的方法不会覆盖默认方法,因为仍允许接口优化abstract来自类层次结构的方法的签名.

您仍然可以使用该方法的默认实现,只需使用以下方法显式调用它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
    }
}
Run Code Online (Sandbox Code Playgroud)

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

  • @arin它可能是可选的,但它有助于防止意外错误(例如拼写错误),任何好的IDE都会在它们丢失时发出警告. (2认同)