乱序链式构造函数

时间:2011-11-22 11:34:39

标签: java inheritance constructor

public class ParentClass
{
    public ParentClass(int param);
}

public class MyClass extends ParentClass
{
    private int _a;
    private int _b;
    private int _c;

    public MyClass(String input)
    {
        _a=CalculateA(input);
        _b=CalculateB(_a);
        _c=CalculateC(_a);
        super(_b+_c);
    }

    //a expensive procedure
    private int CalculateA(String text);

    private int CalculateB(int a);
    private int CalculateC(int a);  
}

Java不允许链接构造函数不是构造函数中放置的第一个方法。 链式构造函数不能将非静态方法作为参数调用(这消除了使用Initialsers返回其初始化值的可能性)。

如何使用合法Java实现上述代码?

2 个答案:

答案 0 :(得分:3)

编辑事实上,Java在调用父类的构造函数之前不允许构造函数进行任何计算,即使这些只涉及静态方法(因为calculateX应该是)并且结果仅分配给类的私有变量(如_a_b_c)或构造函数的本地变量。

有一种解决方法,但是:调用另一个构造函数,并将calculateX调用的结果分配给其参数 - 然后您可以在其他构造函数中访问此结果。

public class MyClass extends ParentClass {
    private int _a,_b,_c;

    public MyClass(String input) {
        this(calculateA(input));
    }

    private MyClass(int a) {
        this(a, calculateB(a), calculateC(a));
    }

    private MyClass(int a, int b, int c) {
        super(b + c);
        this._a = a;
        this._b = b;
        this._c = c;
    }

    private static int calculateA(String text) {
        try {Thread.sleep(1000);} catch (Exception e) {}  // expensive ;-)
        return text.length();
    }

    private static int calculateB(int a) { /* ... */ }
    private static int calculateC(int a) { /* ... */ }
}

编辑2 通过更多计算或更多中间结果存储供以后使用,此方法将导致更长的构造函数链仅包含this(...) - 调用。只有两个构造函数,一个是公共一个和一个私有的更精彩的解决方案,可以使用一个帮助类(合理地是一个内部类):

    public MyClass(String input) {
        this(new InitCalcResult(input));
    }

    private MyClass(InitCalcResult initCalcResult) {
        super(initCalcResult.initB + initCalcResult.initC);
        this._a = initCalcResult.initA;
        this._b = initCalcResult.initB;
        this._c = initCalcResult.initC;
    }

    private static class InitCalcResult {
        private int initA, initB, initC;

        InitCalcResult(String input) {
            initA = calculateA(input);
            initB = calculateB(initA);
            initC = calculateC(initA);  
        }
    }

(使用与上述相同的私有字段和静态calculateX方法。)

答案 1 :(得分:1)

你可以这样做。

public abstract class ParentClass
{
    public ParentClass(String input){
        int a = getData(input);
        /* Do what ever u need to do with a*/
    };

    public abstract int getData(String input);
}


public class MyClass extends ParentClass
{
    private int _a;
    private int _b;
    private int _c;

    public MyClass(String input)
    {
        super(input);
    }

    public int getData(String input){
         _a=CalculateA(input);
         _b=CalculateB(_a);
         _c=CalculateC(_a);
         return _b+_c;
    }

    //a expensive procedure
    private int CalculateA(String text){/* return int */};

    private int CalculateB(int a){/* return int */};
    private int CalculateC(int a){/* return int */};  
}

由于getData是抽象的,因此将调用基类函数。超类将获得所需的数据。