6

我有

class A {

    int var;
    public A(int x) {
        var = x;
    }
}


class B extends A {
     int var2;

     public B(int x, int y) {
         super(...);
         var2 = y;
         x = f(y);
     }
 }

对于子类 B,我需要计算在 A 的构造函数中使用的值 x。如果我可以自由移动super到 my 之下,x=f(y)那么我可以将结果传递给 A(超级)的构造函数。但是 super 必须是 B 的构造函数的第一行。

有什么方法可以第一次用正确的值初始化 A 吗?如果 A.var 是最终的并且我无法在构建后返回并更改它怎么办?

当然,我可以提出super(f(y)),但我可以想象这会变得困难的情况。

4

4 回答 4

10

假设var是私有的并且您需要使用构造函数设置值(这似乎是问题的重点,否则有很多简单的解决方案),我只会使用类似工厂的静态方法来完成。

class B extends A {
     int var2;

     public static B createB(int x, int y) {
         x = f(y);
         return new B(x, y);
     }

     public B(x, y) {
         super(x);
         this.var2 = y;
     }
 }

类似的东西。您别无选择,因为显式构造函数调用必须发生在包装构造函数的第一行。

于 2012-08-02T22:22:52.853 回答
2

你可以这样做:

class B extends A {
    int var2;

    public B(int x, int y) {
        super(calculateX(y));
        var2 = y;
    }

    private static int calculateX(int y) {
        return y;
    }
}

调用静态方法是调用超类构造函数之前唯一可以做的事情。

于 2012-08-02T22:30:43.267 回答
0

替代 hvgotcodes,因为看起来您还想设置 A 的变量...

class B extends A {
 int var2;

 public B(int x, int y) {
     super(x);
     var2 = y;
     x = f(y);
     super.var = ...;
 }
}
于 2012-08-02T22:25:38.480 回答
0

另一种方法可能是向 A 添加一个不带参数的受保护构造函数,该构造函数依赖于延迟初始化:

class A {
    int var;

    public A(int x) {
        var = x;
    }

    /**
    * Just use this constructor if you initialize var
    */
    protected A(int x) {
    }
}

class B extends A {
    int var2;

    public B(int x, int y) {
        super();
        var2 = y;
        var = f(y);
    }
}

但这很难记录,对团队成员来说不是很明显,不应该用于 api。

于 2012-08-02T22:54:44.477 回答