如何处理特定情况下的变量初始化(How to handle initialization of va

2019-10-16 19:16发布

我有一个类,它的构造看起来像下面:

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设置。

现在考虑一类FooPanel扩展BasePanel 。 它需要在其构造几个初始化参数。

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 ,不幸的是没有在这一点上初始化。

什么是重组这个代码,以便在适当的方式:

  • 在需要之前,他们需要的字段设置。
  • 使用该代码FooPanel (和其它图)不受此变化杂乱得多。

任何帮助极大的赞赏。 谢谢。

Answer 1:

你不应该叫从构造函数重写的方法。 你应该做的,在这种情况下,定义一个构造函数初始化只实例字段,并把GUI的初始化在重写initialize()方法,这是不是从构造函数调用。

因此,构建一个FooPanel,你这样做:

FooPanel p = new FooPanel(a, b);
p.initialize();

如果你不会强迫FooPanel的所有客户端要做到这一点,你定义构造私有,并提供一个工厂方法:

public static FooPanel create(A a, B b) {
    FooPanel p = new FooPanel(a, b);
    p.initialize();
    return p;
}


Answer 2:

基本上,尽量避免调用构造函数中的虚拟(即重写)的方法。 这正是导致这类问题。 如果你要调用一个虚方法在构造函数中,你需要记录它 - 很可能避免调用任何其他地方。 这样的方法已被写入处理没有充分尚未初始化的对象,将其放在一个别扭的位置。

很难知道更具体的建议给予没有更多的信息,但我也建议你拥抱过组成继承如果可能的话 - 或者至少总是考虑,并决定最优雅的方法。

如果你真的想在这里传承,你真的需要initializeComponents呢? 不能每个类做自己的构造中有自己的初始化,而不依赖于从它的子类的状态什么?



文章来源: How to handle initialization of variables under specified circumstances