2012-10-04 5 views
7

Gibt es eine gute Möglichkeit, einen Verweis auf ein in einem Konstruktor erstelltes Objekt beizubehalten, das an den Superkonstruktor einer erweiterten Klasse übergeben werden muss (abgesehen davon, dass es vom Super aus zugänglich ist) Klasse oder übergeben Sie es als Parameter in den Konstruktor)?Verweis auf neues Objekt behalten, das in Superkonstruktor übergeben wird

Lassen Sie mich mit einem Beispiel klären. Nehmen Sie diese Klasse (die ich nicht ändern kann und die mir keinen Zugriff auf foo geben):

class TestA { 
    TestA(Object foo) {} 
} 

Nun, ich möchte diese Klasse erstreckt sich wie folgt:

class TestB extends TestA { 
    Object myCopyOfFoo; 

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

Gibt es eine gute Möglichkeit, die erstellten new Object() in myCopyOfFoo zu speichern?

Keiner dieser drei Ideen arbeiten:

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

(Fehler: Konstruktoraufruf die erste Anweisung in einem Konstruktor sein muss)

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

(Fehler: siehe Kann nicht auf eine Instanz Feld myCopyOfFoo beim expliziten Aufrufen eines Konstruktors)

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

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

(Fehler: Kann nicht auf ein i verweisen nstance Verfahren während Aufruf explizit einen Konstruktor)

Ich glaube, ich könnte die folgende tun, aber es ist weder Thread-sicher noch elegant:

static Object tempFoo; 

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

Hat jemand eine bessere Idee für mich? Und warum in aller Welt sind meine ersten beiden Ideen nicht legitim?

Antwort

15

Wie wäre:

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; 
    } 
} 

Da der zweite Konstruktor privat ist, kann es nur innerhalb der gleichen Klasse aufgerufen werden (oder einer umschließenden Klasse) Sie müssen nur sicherstellen, dass alles, was der zweite Konstruktor aufgerufen hat eine geeignete Kopie erstellt, wie es der erste Konstruktor tut.

EDIT: Wenn Ihr echte Situation ist, dass Sie eine Kopie eines vorhandenen Parameter sind unter, dann würde dies funktionieren ...

class ClassB extends ClassA { 
    private final Foo copyOfInput; 

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

Es ist ziemlich hässlich, obwohl :(

+0

Dies sieht aus wie eine gute Lösung, die meinen Code schön tatsächlich paßt, da ich bereits das zweite private Konstruktor in vielen Fällen sowieso bin mit. Ich bin versucht, diese Antwort bereits zu überprüfen, aber es scheint immer noch eine Menge Code zu sein.Ich bezweifle es, aber mal sehen, ob es noch kürzere Vorschläge gibt. Aber danke schon! –

+0

@Markus: Ich habe einen möglichen Vorschlag, wenn Ihr * real * Fall tatsächlich bereits einen Parameter annimmt, und erstellt eine Kopie. Wenn der von Ihnen angegebene Code wirklich repräsentativ ist (d. H. Er erstellt ein neues Objekt aus dem Nichts), würde mein anderer Vorschlag nicht helfen. Ich werde es aber bearbeiten. –

0

Was zu folgenden Themen:

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

    TestB() { 
     super(myCopyOfFoo); 
    } 
} 

Das Objekt wird nur initialisiert werden, wenn ein neues Objekt TestB zu schaffen, so im Wesentlichen das, was tut yo Du willst?

+1

Nein, bekomme den Fehler "kann nicht auf myCopyOfFoo verweisen, bevor der Supertype-Konstruktor aufgerufen wurde" –

+1

Das andere Problem dabei ist, dass der Compiler die Initialisierung von myCopyOfFoo in den TestB() - Konstruktor einbindet. Also, selbst wenn es keinen Fehler geworfen hätte, würde es super() mit null statt dem neuen Objekt aufrufen. –

1

Eine weitere Option:

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); 
    } 

}