I want to define some common post-construction behavior for a group of classes. When you have shared behaviors in different classes, Java tells us to extract them out into a parent class.
Conceptually, it makes sense, we're saying, for objects of this type (and its subclasses), do some post-processing after it's constructed;
Practically, it's hard to do. You obviously can't put it in the parent class constructor because parent constructor is called before the subclass constructor. I could write a postInit() method in the parent class and require all subclasses to call it as their last statement in their constructors, but it doesn't seem very clean, as there's no way to enforce it, and people do forget.
Is there maybe some language construct that I'm not aware of that may solve my problem?
Thanks
Just a little more background on the requirement. Factory methods etc. that are suggested by many of the answers (which I've upvoted) below are all good ideas, but I don't really have that luxury. The actual situation is this, I have this parent class, which is extended by a couple of dozen subclasses, which are in turn used in many other places. So redesign how these subclasses are used is out of the question, and changing all subclasses is borderline possible. Ideally, I just need to change the parent class, so that's what I'm asking.
Constructors are not inherited. The superclass constructor can be called from the first line of a subclass constructor by using the keyword super and passing appropriate parameters to set the private instance variables of the superclass.
A subclass inherits all the members (fields, methods, and nested classes) from its superclass. Constructors are not members, so they are not inherited by subclasses, but the constructor of the superclass can be invoked from the subclass.
Invocation of a superclass constructor must be the first line in the subclass constructor.
The Sun compiler says, call to super must be first statement in constructor . The Eclipse compiler says, Constructor call must be the first statement in a constructor . So, it is not stopping you from executing logic before the call to super() .
If you can't use a factory method for pragmatic reasons, the best solution I can think of is to create a protected final
method in the root class that does the post processing, and add a call to the method to each and every leaf class; e.g.
public abstract class Root {
...
protected final void finishInit() {
// Do post-processing
}
}
public abstract class Intermediate {
...
protected Intermediate(...) {
super(...);
...
// don't call finishInit();
}
...
}
public class Leaf {
...
public Leaf(...) {
super(...);
...
finishInit();
}
...
}
If Intermediate
is not abstract
then you need a separate public constructor to create instances that calls finishInit()
at the end.
It's all a bit clumsy, but that's the penalty you have to pay if you can't/won't refactor your code to use factory methods.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With