我有一个Wicket页面类,它根据抽象方法的结果设置页面标题。
public abstract class BasicPage extends WebPage {
public BasicPage() {
add(new Label("title", getTitle()));
}
protected abstract String getTitle();
}
NetBeans用“构造函数中可重写方法调用”的消息警告我,但是它应该有什么问题呢?我能想到的唯一替代方法是将抽象方法的结果传递给子类中的超构造函数。但考虑到很多参数,这可能很难解读。
在Wicket的具体情况下:这就是我问Wicket的原因
开发人员在构建组件的框架生命周期中增加了对显式的两阶段组件初始化过程的支持。
构造——通过构造函数
初始化-通过oninitialize(在构造虚拟方法工作后!)
关于是否有必要(恕我直言,这是完全必要的),有相当活跃的辩论,因为这个链接展示了http://apache-wicket.1842946.n4.nabble.com/VOTE-WICKET-3218-Component-onInitialize-is-broken-for-Pages-td3341090i20.html)
好消息是,Wicket的优秀开发人员最终引入了两阶段初始化(使最出色的Java UI框架更加出色!),所以在Wicket中,你可以在onInitialize方法中完成所有的构造后初始化,如果你重写它,框架会自动调用它——在组件生命周期的这一点上,它的构造函数已经完成了它的工作,因此虚拟方法可以正常工作。
下面的示例揭示了在超级构造函数中调用可重写方法时可能出现的逻辑问题。
class A {
protected int minWeeklySalary;
protected int maxWeeklySalary;
protected static final int MIN = 1000;
protected static final int MAX = 2000;
public A() {
setSalaryRange();
}
protected void setSalaryRange() {
throw new RuntimeException("not implemented");
}
public void pr() {
System.out.println("minWeeklySalary: " + minWeeklySalary);
System.out.println("maxWeeklySalary: " + maxWeeklySalary);
}
}
class B extends A {
private int factor = 1;
public B(int _factor) {
this.factor = _factor;
}
@Override
protected void setSalaryRange() {
this.minWeeklySalary = MIN * this.factor;
this.maxWeeklySalary = MAX * this.factor;
}
}
public static void main(String[] args) {
B b = new B(2);
b.pr();
}
结果实际上是:
minWeeklySalary: 0
最大每周工资: 0
这是因为类B的构造函数首先调用类A的构造函数,在那里执行B内部的可重写方法。但是在方法内部,我们使用的实例变量factor还没有初始化(因为A的构造函数还没有完成),因此factor是0而不是1,也肯定不是2(程序员可能认为它会是2)。想象一下,如果计算逻辑扭曲十倍,跟踪错误将是多么困难。
我希望这能帮助到一些人。