需要覆盖方法才能调用super

我希望当子类重写父类中的方法时,在该子方法中调用super.method()

有没有办法在编译时检查这个?
如果没有,当发生这种情况时,我将如何抛出运行时exception?

没有办法直接要求这个。 但是,你可以做的是:

 public class MySuperclass { public final void myExposedInterface() { //do the things you always want to have happen here overridableInterface(); } protected void overridableInterface() { //superclass implemention does nothing } } public class MySubclass extends MySuperclass { @Override protected void overridableInterface() { System.out.println("Subclass-specific code goes here"); } } 

这提供了一个内部接口点,子类可以使用它来向公共myExposedInterface()方法添加自定义行为,同时确保始终执行超类行为,无论子类做什么。

解:

看看findBugs项目……

  • FindBugs的
    • 注释包

示例……

  import javax.annotation.OverridingMethodsMustInvokeSuper; : @OverridingMethodsMustInvokeSuper protected String getLabel(){ ... } 

覆盖:

  @Override protected String getLabel(){ // no call to Super Class!! // gives a message ... } 

我已经使用它大约3年了。 没有小猫受到伤害。

遗憾的是,没有办法在编译时要求它,并且无法在运行时检测它(除非有一些特定于应用程序的逻辑或事件序列可用于检测未被调用的方法)。 最好的办法是大量记录方法。

如果你真的,真的想沿着这条路走下去,你可以使用这样的模式:

 public class BaseClass { public final void myMethod() { // do special stuff here which must always happen ... // allow subclasses to customize myMethod() here myMethodCustom(); } protected void myMethodCustom() { // base class does nothing } } 

好吧,我可以假设超类方法中的初始化在别处使用。 我会在超类方法中设置一个标志,稍后在需要初始化时检查它。 更具体地说,让我们说setupPaint()是需要始终被调用的超类方法。 那么我们可以这样做:

 class C { private boolean paintSetupDone = false; void setupPaint() { paintSetupDone = true; ... } void paint() { // requires that setupPaint() of C has been called if (!paintSetupDone) throw RuntimeException("setup not done"); ... } } 

现在,如果C的子类没有调用setupPaint()函数,则无法设置(私有)标志,并且需要对超类setupPaint()进行契约调用的方法(例如paint())将能够检查并抛出该exception。

正如其他地方所指出的那样,在java中无法要求这样的合同。

在编译时没有办法检查这个。 (但是,我听说过你可以在编译时使用注释来做这些建议,虽然我从未见过特定的注释解决方案,但我不知道它是如何完成的。)对于一种抛出exception的方法运行时,看到这个post 。 也许你可以重构你的代码,以便基类有一个包含基本部分的final方法,并调用一个不需要super调用的非final方法。

如果你自己打电话怎么样? 而不是将实现指定给子类(您实际上无法做到),只需使用基类的接口和实现来强制执行它。

 public abstract class BaseClass { public final void callMeFirst() { // method that needs to be called before subclassing method runs } public final void makeSureWhateverGetsCalled() { callMeFirst(); overrideMe(); } public abstract void overrideMe(); } public class OverridingClass extends BaseClass { @Override public void overrideMe() { // do whatever needs to be done AFTER callMeFirst() is run } }