Here's a contrived example: (Naming scheme used in actual code is too confusing)
I've got a class Father that extends Grandfather which is a part of a 3rdparty library that cannot be altered. I also have a few classes that extend Father; Son for example. Grandfather has a constructor that looks like this:
public Grandfather(String name) {...}
What actually happens inside this constructor is not important. What is important is that whatever it is doing MUST also be done by all derived classes, thus a call to super(String)
is the obligatory first line of every derived class' constructor(s). The implication here is that the constructors of all descendants of Grandfather, no matter how far removed must always make a call to super (or a chained constructor that calls super) as its first line.
Inside my Father implementation I have a method configure(String xml)
which parses an xml file and uses reflection to set various parameters inside the instance. Some of these parameters are in Grandfather, some are in Father and some may even be in Son. Configure needs to run every time a class derived from Father is instantiated. My initial thought was to simply add a call to configure(String)
to my Father constructor like this:
public Father(String name, String xml) extends Grandfather {
super(name);
configure(xml);
}
This works fine for Granfather and Father instantiations but breaks down on Son instantiations for essentially the same reason that calling an overridable method from within a constructor will typically break down. Consider the following Son implementation:
public class Son extends Father {
private String occupation = "unknown";
public Son(String name, String xml) {
super(name, xml);
}
}
Here's what happens:
- A new Son is instantiated using
new Son(String, String)
. - Within
Son(String, String)
a call tosuper(String, String)
is made, ie.Father(String, String)
. - Within
Father(String, String)
configure(String)
is called. configure(String)
finds an<occupation>
element and using reflection invokessetOccupation("Coal Miner")
.Father(String, String)
exits and execution returns toSon(String, String)
.- Right before Son exits all members with supplied defaults are set (this is inlined at the end of the constructor in Java)
- occupation is overwritten by the inlining and is set to "unknown".
I'd like to avoid repetitive calls to configure(String)
since it is a potentially expensive operation, so adding a call to configure(String)
at the end of every constructor is out. (This would result in configure(String)
being called twice for Son instances and n times for n'th generation descendants.
I'd also like to avoid having to manually call configure(String)
after instantiating Father or any of it's descendants:
Son s = new Son(...);
s.configure(...);
A factory method would work beautifully here but due to the way that Grandfather instances are used, it is not possible. Long story short, I am almost never the one that instantiates these classes and have zero access to the code that does.
Or in other words, doing the following:
Father f = new Father(...);
would result in configure(...)
being called exactly one time by the Father constructor while at the same time:
Son s = new Son(...);
would result in configure(...)
being called exactly one time by the Son constructor.
Given these constraints, can anybody think of a way to accomplish my objective or am I screwed?