这是一个人为的例子:(在实际代码中使用的命名方案太混乱了)
我有一个班级父亲,扩展了祖父,这是第三方图书馆的一部分,无法改变。我也有一些课程延伸父亲;儿子,例如。祖父有一个看起来像这样的构造函数:
public Grandfather(String name) {...}
这个构造函数中实际发生的事情并不重要。重要的是,无论它做什么,也必须由所有派生类完成,因此对super(String)
的调用是每个派生类'构造函数的强制性第一行。这里的含义是,祖父的所有后代的构造函数,无论移除多远,都必须始终调用super(或称为super的链式构造函数)作为其第一行。
在我的Father实现中,我有一个方法configure(String xml)
,它解析xml文件并使用反射在实例中设置各种参数。其中一些参数在祖父中,一些在父亲中,一些甚至可能在儿子中。每次从父派生的类实例化时,都需要运行配置。我最初的想法是简单地将configure(String)
的调用添加到我的父构造函数中,如下所示:
public Father(String name, String xml) extends Grandfather {
super(name);
configure(xml);
}
这适用于Granfather和Father实例化,但在Son实例化上分解,原因与在构造函数中调用可覆盖方法通常会分解的原因相同。考虑以下Son实现:
public class Son extends Father {
private String occupation = "unknown";
public Son(String name, String xml) {
super(name, xml);
}
}
以下是发生的事情:
new Son(String, String)
实例化新的Son。Son(String, String)
内,对super(String, String)
进行了调用,即。 Father(String, String)
。Father(String, String)
configure(String)
内召唤。configure(String)
找到<occupation>
元素并使用反射调用setOccupation("Coal Miner")
。Father(String, String)
退出并执行返回Son(String, String)
。我想避免重复调用configure(String)
,因为这是一个可能很昂贵的操作,所以在每个构造函数的末尾添加一个对configure(String)
的调用。 (这将导致configure(String)
为Son实例调用两次,为第n代后代调用n次。
我还想避免在实例化父亲或其任何后代之后手动调用configure(String)
:
Son s = new Son(...);
s.configure(...);
工厂方法在这里可以很好地工作但是由于使用祖父实例的方式,这是不可能的。简而言之,我几乎从不会实例化这些类,并且无法访问代码。
或换句话说,执行以下操作:
Father f = new Father(...);
会导致configure(...)
被父构造函数同时调用一次{/ p>
Son s = new Son(...);
会导致configure(...)
被Son构造函数一次调用。
鉴于这些限制,任何人都可以想出实现目标的方法,还是我搞砸了?
答案 0 :(得分:1)
从你的声明中看来,你并不是真的反对在ctor末尾显式调用configure。
那么,这种扭曲是否可以接受?
class GrandFather {
GrandFather(String name, boolean configure) {
// some init
if (configure) {
configure(name);
}
}
GrandFather(String name) {
this(name, true);
}
}
class Father {
Father(String name, boolean configure) {
super(name, false);
// some init
if (configure) {
configure(name);
}
}
Father(String name) {
this(name, true);
}
}
class Son {
Son(String name, boolean configure) {
super(name, false);
// some init
if (configure) {
configure(name);
}
}
Son(String name) {
this(name, true);
}
}
这个想法是,每个继承的类调用在它们的构造函数中显式配置,但它要求父级不要自己配置。