简体   繁体   中英

Java, Call overridden method implicitly

Right now in some Java code I have something like this

class A {
 void f() {

 }
 A() {
  f();
 }
}

class B extends A{
 @Override
 void f() {
  //do some stuff
  super.f();
 }
}

class C extends B {
 @Override
 void f() {
  //do some stuff
  super.f();
 }
}

I want to have f() called and then iterate upwards through each parent class, running the overridden f() . I do this by calling super.f() explicitly, although I'd like to not have to do this.

The reason why I do this is there post processing that must be done after the constructor in A is reached. And there is state in each class that much be properly init'd, which is why we have the upward trace of f() 's.

So the constructor of A is really

A() {
  //init some state in a
  f(); //run f(), which will depend on the previous operation
}

If I do something like new C(); I want Cf() called, then Bf() called, then Af() called

Anyway, if there is a smarter way of doing this, I'm open to it.

Calling non-final methods in a constructor is generally a bad idea - at the very least, I'd suggest you document it heavily . Bear in mind that when f() is called, C's constructor won't have been called - and neither will any variable initializers. The object is only half-initialized, and so methods will need to be written very carefully.

There's no way of implicitly calling super.f() though in normal Java. Given the large warnings I'd be putting around that code, a single statement is far from the end of the world :)

If you want to verify that it's called, you could always check for the results of Af() in A's constructor immediately after the call - that will check that the call has reached the top level.

This may help you somewhat - it's a way to enforce that the child class calls the super; this would help you detect developer mistakes where the implementer of a child class forgot to continue the call up the chain to super.f():

class A {
 boolean fDone;

 public final void f() {
  fDone = false;
  doF();
  if (!fDone) {
   throw new IllegalStateException("super.f() was not called");
  }
 }

 protected void doF() {
  //do some operation
  fDone = true;
 }
}

class B extends A {
 protected void doF() {
  //some operation, maybe repeat this pattern of using a flag to enforce super call
  super.doF();
 }
}

So, the child overrides doF(), but is required to call super.doF();

As far as I know, there's no way to do this. AspectJ might do something similar to this, but then you'd have to tag it with an annotation, I suppose, which is hardly less work than just calling super.f() . You need to signify that the superclass method is being called, because you need to have the ability to make that decision for each subclass separately - otherwise, you might have a subclass that doesn't want to delegate anything to the superclass at all - so the default is that you just put in the code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM