2012-10-04 12 views
7

コンストラクタ内で作成されたオブジェクトへの参照を維持するよい方法は、拡張クラスのスーパーコンストラクタに渡す必要があるクラスとして渡すか、コンストラクタにパラメータとして渡します)?スーパーコンストラクタに渡される新しいオブジェクトへの参照を保持する

例を用いて明確にしてください。 (私は変更することはできませんし、これは私にfooへのアクセス権を与えるものではありません)このクラスを取る:

class TestA { 
    TestA(Object foo) {} 
} 

、私は次のようにこのクラスを拡張したいと思います:

class TestB extends TestA { 
    Object myCopyOfFoo; 

    TestB() { 
     super(new Object()); 
    } 
} 

があります作成したnew Object()を保存する良い方法はmyCopyOfFooですか?

どちらもこれら三つのアイデアの一つは仕事:

TestB() { 
    myCopyOfFoo = new Object(); 
    super(myCopyOfFoo); 
} 

(エラー:コンストラクタの呼び出しは、コンストラクタの最初のステートメントでなければなりません)

TestB() { 
    super(myCopyOfFoo = new Object()); 
} 

(エラー:インスタンスフィールドのmyCopyOfFooを参照することはできませんコンストラクタを明示的に呼び出す)

TestB() { 
    super(makeFoo()); 
} 

Object makeFoo() { 
    myCopyOfFoo = new Object(); 
    return myCopyOfFoo; 
} 

(エラー:iを参照できません明示的にコンストラクターを起動している間nstance法)

私は、次の操作を行うことができると思いますが、それは、スレッドセーフでもエレガントでもないです:

static Object tempFoo; 

TestB() { 
    super(tempFoo = new Object()); 
    myCopyOfFoo = tempFoo; 
} 

誰も私のためのより良いアイデアを持っていますか?なぜ私の最初の2つのアイデアは合法ではないのですか?

についてどのように

答えて

15

:二コンストラクタはプライベートであるため

class TestB extends TestA { 
    Object myCopyOfFoo; 

    // I assume you actually wanted this to take a parameter called foo? 
    // I've left it as per the question... 
    TestB() { 
     this(new Object()); 
    } 

    private TestB(Object copy) { 
     super(copy); 
     myCopyOfFoo = copy; 
    } 
} 

、それだけで同じクラス(または囲むクラス)の中に呼び出すことができますので、あなただけの二コンストラクタを呼び出すものが持っていることを確認する必要があります最初のコンストラクタが行うように、適切なコピーを作成しました。

EDIT:あなたの本当の状況では、既存のパラメータのコピーを取っているということであれば、これは動作します...

class ClassB extends ClassA { 
    private final Foo copyOfInput; 

    ClassB(Foo input) { 
     super(input = input.clone()); 
     copyOfInput = input; 
    } 
} 

それはしかし、かなり醜いです:(

+0

これは、私はすでにとにかく多くの場合、第2のプライベートコンストラクタを使用していますので、実際には、うまく自分のコードに合った良い解決策のように見えます。私はすでにこの回答にチェックマークを付けるように誘惑されていますが、まだ多くのコードのようです。私はそれを疑うが、もっと短い提案があるかどうかを見てみよう。しかし、すでにありがとう! –

+0

@Markus:あなたの*実際のケースが実際にすでにパラメータを受け取り、コピーを作成しているなら、私は潜在的な提案があります。あなたが指定したコードが本当に代表的なものであれば(つまり、新しいオブジェクトを何も作成していない)、私の他の提案は役に立たないでしょう。私はそれを編集します。 –

0

class TestB extends TestA { 
    Object myCopyOfFoo = new Object(); 

    TestB() { 
     super(myCopyOfFoo); 
    } 
} 

オブジェクトは、新しいオブジェクトTestBを作成するときにのみ初期化されるため、本質的にこれは何を行うのでしょうかほしい?

+1

いいえ、スーパータイプのコンストラクターが呼び出される前に "myCopyOfFooを参照できません"というエラーが表示される –

+1

これのもう1つの問題は、コンパイラーがTestB()コンストラクターにmyCopyOfFooの初期化をインライン化することです。したがって、エラーをスローしなくても、新しいObjectではなくnullでsuper()を呼び出すことになります。 –

1

別のオプション:

public class TestB extends TestA { 

    Object myCopyOfFoo; 

    private TestB(Object foo) { 
     super(foo); 
     myCopyOfFoo = foo; 
    } 

    public static TestB createInstance() { 
     Object foo = new Object(); 
     return new TestB(foo); 
    } 

} 
関連する問題