是否可以在构造函数中的 super() 之前进行计算?

2022-08-31 11:23:43

假设我有一个类 Base,它有一个参数构造函数,其中一个 TextBox 对象作为它的参数。如果我有一个以下形式的类简单:

public class Simple extends Base {
  public Simple(){
    TextBox t = new TextBox();
    super(t);
    //wouldn't it be nice if I could do things with t down here?
  }
}

我会收到一个错误,告诉我对 super 的调用必须是构造函数中的第一个调用。但是,奇怪的是,我可以做到这一点。

public class Simple extends Base {
  public Simple(){
    super(new TextBox());
  }
}

为什么这是允许的,但第一个例子不是?我可以理解需要首先设置子类,并且可能不允许在调用超构造函数之前实例化对象变量。但是t显然是一个方法(局部)变量,那么为什么不允许它呢?

有没有办法绕过这个限制?有没有一种好的、安全的方法来保存变量,这些变量可以在调用 super 之前但在你进入构造函数之后构造?或者,更一般地说,允许在实际调用super之前完成计算,但是在构造函数中?

谢谢。


答案 1

是的,对于您的简单案例,有一个解决方法。您可以创建一个私有构造函数,该构造函数作为参数,并从公共构造函数中调用该参数。TextBox

public class Simple extends Base {
    private Simple(TextBox t) {
        super(t);
        // continue doing stuff with t here
    }

    public Simple() {
        this(new TextBox());
    }
}

对于更复杂的东西,你需要使用工厂或静态工厂方法。


答案 2

我在超级调用之前遇到了同样的计算问题。有时您希望在调用 之前检查一些条件。例如,您有一个类,该类在创建时使用大量资源。子类需要一些额外的数据,并且可能希望在调用超级构造函数之前先检查它们。有一个简单的方法来解决这个问题。可能看起来有点奇怪,但它效果很好:super()

在类中使用一个私有静态方法,该方法返回超构造函数的参数,并在其中进行检查:

public class Simple extends Base {
  public Simple(){
    super(createTextBox());
  }

  private static TextBox createTextBox() {
    TextBox t = new TextBox();
    t.doSomething();
    // ... or more
    return t;
  }
}

推荐