@MustOverride注释?

时间:2010-04-30 05:27:21

标签: java interface annotations abstract-class override

在.NET中,可以为特定超类中的方法指定“mustoverride”属性,以确保子类覆盖该特定方法。 我想知道是否有人有一个可以达到相同效果的自定义java注释。基本上我想要的是推动子类覆盖超类中的方法,该超类本身具有一些必须贯穿的逻辑。我不想使用抽象方法或接口,因为我想在super方法中运行一些常用功能,但或多或​​少会产生编译器警告/错误,表示派生类应该覆盖a给定的方法。

7 个答案:

答案 0 :(得分:19)

我不太明白为什么你不想使用abstract修饰符 - 这是用于强制子类实现,只需要用于某些方法,而不是全部。或许您正在考虑C ++风格的“纯抽象”类?

但许多Java开发人员不知道的另一件事是,它也可以覆盖非抽象方法并将它们声明为抽象方法;像:

public abstract String toString(); // force re-definition

这样即使java.lang.Object已经定义了一个实现,你也可以强制子类再次定义它。

答案 1 :(得分:12)

忽略抽象方法,Java中没有这样的工具。也许有可能创建一个编译时注释来强制这种行为(我不相信它)但是就是这样。

真正的踢球者是“覆盖超类中的一个方法,该方法本身有一些必须通过的逻辑”。如果重写方法,除非明确调用它,否则不会调用超类的方法。

在这种情况下,我倾向于做类似的事情:

abstract public class Worker implements Runnable {
  @Override
  public final void run() {
    beforeWork();
    doWork();
    afterWork();
  }

  protected void beforeWork() { }
  protected void afterWork() { }
  abstract protected void doWork();
}

通过接口的方法强制使用特定的逻辑结构。例如,您可以使用它来计算调用,而不必担心用户是否调用super.run()等。

答案 2 :(得分:5)

...如果声明基类abstract不是一个选项,你总是可以抛出UnsupportedOperationException

class BaseClass {
    void mustOverride() {
        throw new UnsupportedOperationException("Must implement");
    }
}

但这当然不是编译时检查......

答案 3 :(得分:4)

我不确定你在.NET中考虑哪个属性。

在VB中,您可以将MustOverride 修饰符应用于方法,但这相当于在Java中使用抽象方法。您不需要属性/注释,因为该概念已内置于语言中。它不仅仅是应用元数据 - 抽象方法本身也不包含任何实现,这也是至关重要的区别。

如果你认为有这样的属性,请问你的意思是哪一个?

答案 4 :(得分:2)

Android在Google I / O 2015中宣布了一个新的注释: @callSuper

此处有更多详情: http://tools.android.com/tech-docs/support-annotations

答案 5 :(得分:1)

如果你需要一些默认行为,但由于某种原因它不应该被专业化使用,比如非抽象适配器类中的逻辑实现只是为了便于原型设计,但不应该在生产中使用,例如,您可以封装该逻辑并记录它正在使用的警告,而无需实际运行它。

基类构造函数可以检查包含逻辑的变量是否指向默认值。 (以非常抽象的方式写作,因为我认为它应该适用于任何语言)

这将是类似的(未编译,未经测试和不完整)Java(最多7个)示例:

public interface SomeLogic {
 void execute();
}

public class BaseClass {

  //...private stuff and the logging framework of your preference...

  private static final SomeLogic MUST_OVERRIDE = new SomeLogic() {
    public void execute() {
      //do some default naive stuff
    }
  };

  protected SomeLogic getLogic() { return MUST_OVERRIDE; }

  //the method that probably would be marked as MustOverride if the option existed in the language, maybe with another name as this exists in VB but with the same objective as the abstract keyword in Java
  public void executeLogic() {
    getLogic().execute();
  }

  public BaseClass() {
    if (getLogic() == MUST_OVERRIDE) {
      log.warn("Using default logic for the important SomeLogic.execute method, but it is not intended for production. Please override the getLogic to return a proper implementation ASAP");
    }
  }

}

public GoodSpecialization extends BaseClass {

  public SomeLogic getLogic() {
    //returns a proper implementation to do whatever was specified for the execute method
  }

  //do some other specialized stuff...
}

public BadSpecialization extends BaseClass {

  //do lots of specialized stuff but doesn't override getLogic...
}

根据要求,有些事情可能会有所不同,而且显然更简单,特别是对于具有lambda表达式的语言,但基本思想是相同的。

如果没有内置的东西,总会有一些方法来模拟它,在这个例子中,你会在一个日志文件中得到一个运行时警告,它带有一个类似自制模式的解决方案,只有你的需要才能指出它足够或更硬核字节码操作,ide插件开发或任何需要的魔法。

答案 6 :(得分:-1)

我一直在想这个。

虽然我不知道有任何方法需要编译错误,但如果您忘记覆盖,可以尝试编写自定义PMD规则来引发红旗。

如果你选择覆盖equals,已经有大量的PMD规则可以提醒你实现HhashCode。或许可以这样做。

我之前从未这样做过,所以我不是那个写教程的人,但是一个好的起点就是这个链接http://techtraits.com/programming/2011/11/05/custom-pmd-rules-using-xpath/在这个例子中,他基本上会创建一个警告,如果你决定在导入包中使用通配符。使用它作为起点来探索PMD如何分析您的源代码,访问层次结构的每个成员,以及确定您忘记实现特定方法的位置。

注释也是一种可能性,但您必须找到自己的方法来实现类路径中的导航。我相信PMD已经处理过了。此外,PMD与IDE有一些非常好的集成。 https://pmd.github.io/