[英]Alternatives to using overridden methods in constructors, Java
在我编写的Java项目中,我最终使用了在构造函数中重写的方法。 就像是:
class SuperClass {
SuperClass() {
intialise();
}
protected void initialise() {
//Do some stuff common to all subclasses
methodA();
methodB();
}
protected abstract void methodA();
protected abstract void methodB();
}
class SubClass1() {
SubClass() {
super();
}
protected void methodA() { //Do something }
protected void methodB() { //Do something }
}
class SubClass2() {
SubClass() {
super();
}
protected void methodA() { //Do something else }
protected void methodB() { //Do something else}
}
我现在意识到,虽然在我的情况下它工作正常,但是有点危险,因为SubClass方法在一个目前只被构造为SuperClass对象的对象上调用(当扩展SuperClass的新类被添加时,可能会忽略这一点)未来)。 由于对象的创建方式不同,它在c ++中也不起作用。
我能想到的唯一方法就是将initialise方法调用向下移动到具体的类构造函数:
class SuperClass {
SuperClass() {
}
protected void initialise() {
methodA();
methodB();
}
protected abstract void methodA();
protected abstract void methodB();
}
class SubClass1() {
SubClass() {
super();
initialise();
}
protected void methodA() { //Do something }
protected void methodB() { //Do something }
}...
这是解决这个问题的常用方法吗? 扩展SuperClass的所有其他类需要记住调用initialise()似乎是一种耻辱(并且容易忘记)。
我还发现自己在更复杂的情境中做了类似的事情,它在构造函数中使用了Factory方法,在子类中重写它以决定实现哪个具体类。 我能想到的唯一另一种方法是将这种设计模式保持原样,或许可以构建一个两阶段的过程; 即用最小的构造,然后调用第二种方法来完成工作。
需要初始化的对象实际上需要通过工厂方法创建。 你确实提到了一个工厂,但是从构造函数中调用,所以这听起来也不像是简单的方法。 如果你只是在基类中有一个工厂,公共不可见的构造函数,以及一个决定返回哪个具体类的机制,那么工厂将很容易地执行初始化策略。
这实际上不是一个好主意,因为当调用其methodA()和methodB()时,您的子类将无法正确构造。 对于扩展课程的人来说,这将是非常混乱的。 建议您使用抽象的init()
,如dlev在他/她的评论中所建议的那样。
我想知道你是否让事情变得比他们需要的更复杂。
在您的示例中,methodA的每个实现所完成的工作可以移动到执行该实现的类的构造函数中。 因此,不要使用SubClass :: methodA,只需将逻辑移动到SubClass构造函数中。
如果你这样做,你可以获得清晰,代价是可能难以理解对各种初始化位执行顺序的控制。
Bruce Eckel在他的“Thinking in Java”中提出的建议是使你的methodA()和类SuperClass的方法B()最终或私有(隐式最终),因此它们可以从超类构造函数访问,尽管没有派生类会有访问这些方法,因此,不会有任何危险的覆盖 - 任何派生类中声明的类似签名的任何方法都只是新方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.