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 C.f()
called, then B.f()
called, then A.f()
called
Anyway, if there is a smarter way of doing this, I'm open to it.
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.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
A.f()
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():
So, the child overrides doF(), but is required to call super.doF();