问题描述
我有一个其构造函数如下所示的类:
I have a class whose constructor looks something like below:
abstract class BasePanel extends JPanel {
public BasePanel(A a) {
// initializing fields from values passed to ctor
this.a = a;
// initializing gui components
initializeComponents();
setupPanels();
concludeUiSetup();
}
// stuff
}
在构造函数中,首先使用要传递给构造函数的值初始化要初始化的字段.然后依次调用UI设置所需的其他方法.在特定于它们的UI设置的子类中,需要重写其中的两种方法.
In the constructor, first the fields that are to be initialized with values passed to constructor are initialized. Then other methods required for UI setup are called in order. Two of these methods need to be overridden in subclass for UI setup specific to them.
现在考虑扩展BasePanel
的类FooPanel
.它的构造函数中还需要一些初始化参数.
Now consider a class FooPanel
that extends BasePanel
. It requires a few more initialization parameters in its constructor.
class FooPanel extends BasePanel {
public FooPanel(A a, B b) {
super(a);
this.b = b;
}
@Override
public void initializeComponents() {
super.initializeComponents();
// I require b here, but oops, b is not initialized at this point, and so
// this will throw NPE.
someTextField.setText(b.get());
}
// stuff
}
initializeComponents
方法在这里需要b
,不幸的是,此时尚未初始化.
initializeComponents
method here requires b
, which unfortunately is not initialized at that point.
重新构造此代码的合适方法是什么:
What would be the appropriate way to restructure this code so that:
- 必填字段是在需要之前设置的.
- 使用
FooPanel
(和其他面板)的代码不会因此更改而变得杂乱无章.
- the fields required are set before they're needed.
- the code that uses
FooPanel
(and other panels) isn't cluttered to much by this change.
任何帮助,我们将不胜感激.谢谢.
Any help greatly appreciated. Thanks.
推荐答案
您不应从构造函数中调用可重写的方法.在这种情况下,您应该做的是定义一个仅初始化实例字段的构造函数,然后将GUI的初始化放入可重写的initialize()方法中,该方法不会从构造函数中调用.
You should not call overridable methods from a constructor. What you should do, in this case, is defining a constructor that only initializes instance fields, and put the initialization of the GUI in an overridable initialize() method, which is not called from the constructor.
因此,要构建FooPanel,请执行以下操作:
So, to construct a FooPanel, you do:
FooPanel p = new FooPanel(a, b);
p.initialize();
如果您不强迫FooPanel的所有客户端执行此操作,则将构造函数定义为私有,并提供工厂方法:
And if you won't force all the clients of FooPanel to do that, you define the constructor private, and provide a factory method:
public static FooPanel create(A a, B b) {
FooPanel p = new FooPanel(a, b);
p.initialize();
return p;
}
这篇关于在特定情况下如何处理变量的初始化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!