Require override of method to call super

前端 未结 7 2348
既然无缘
既然无缘 2020-12-17 08:11

I want that when a child class overrides a method in a parent class, the super.method() is called in that child method.

Is there any way to check this a

相关标签:
7条回答
  • 2020-12-17 08:41

    solution:

    Look at the findBugs project ...

    • FindBugs
      • Annotations package

    Example ...

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

    Override:

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

    I've been using it for about 3 years. No kittens have been harmed.

    0 讨论(0)
  • 2020-12-17 08:45

    unfortunately, there's no way to require it at compile time, and no way to detect it at runtime (unless there is some app specific logic or sequence of events that you could use to detect the method not being called). best thing to do is heavily document the method.

    if you really, really want to go down this path, you could use something like this pattern:

    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
      }
    }
    
    0 讨论(0)
  • 2020-12-17 08:47

    Well, I can presume that the initialization in the superclass method is used elsewhere. I would set a flag in the superclass method and check it later when the initialization is needed. More specifically, let's say setupPaint() is superclass method that needs always to be called. so then we can do:

    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");
         ...
      }
    }
    

    Now if a subclass of C doesn't call the setupPaint() function, there's no way that the (private) flag will be set, and methods requiring the contractual call to the superclass setupPaint(), such as paint() will be able to check and throw that exception.

    As noted elsewhere, there is by the way no way of requiring such a contract in java.

    0 讨论(0)
  • 2020-12-17 08:54

    There's not a way to check for this at compile time. (However, I've heard suggestions that you could do this at compile time with annotations, although I've never seen a specific annotation solution and I don't know how it would be done.) For a way to throw an exception at run time, see this thread. Perhaps you can refactor your code so that the base class has a final method that includes the essential parts and calls a non-final method that does not require a super call.

    0 讨论(0)
  • 2020-12-17 09:02

    There's no way to require this directly. What you can do, however, is something like:

    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");
        }
    }
    

    This provides an internal interface-point that subclasses can use to add custom behavior to the public myExposedInterface() method, while ensuring that the superclass behavior is always executed no matter what the subclass does.

    0 讨论(0)
  • 2020-12-17 09:05

    How about if you make the call yourself? Instead of dictating implementation to a subclass (which you really can't do) just enforce it with the interface and implementation of your baseclass.

    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
        }
    }
    
    0 讨论(0)
提交回复
热议问题