2010-10-07 14 views
5

To właśnie staram się robić (Java 1.6):Jak zaimplementować zawijanie konstruktorów w Javie?

public class Foo { 
    public Foo() { 
    Bar b = new Bar(); 
    b.setSomeData(); 
    b.doSomethingElse(); 
    this(b); 
    } 
    public Foo(Bar b) { 
    // ... 
    } 
} 

Compiler mówi:

call to this must be first statement in constructor 

Czy istnieje obejście tego problemu?

Odpowiedz

17

Trzeba wdrożyć go tak:

public class Foo { 
    public Foo() { 
    this(makeBar()); 
    } 
    public Foo(Bar b) { 
    // ... 
    } 
    private static Bar makeBar() { 
    Bar b = new Bar(); 
    b.setSomeData(); 
    b.doSomethingElse(); 
    return b; 
    } 
} 

Sposób makeBar powinna być statyczna, ponieważ obiekt odpowiadający this nie jest dostępny w punkcie jesteś wywołanie metody.

Nawiasem mówiąc, takie podejście ma tę zaletę, że robi przekazać w pełni zainicjowany Bar obiekt do Foo(Bar). (@RonU zauważa, że ​​jego podejście nie. To oczywiście oznacza, że ​​jego Foo(Bar) konstruktor nie można zakładać, że jego Foo argument jest w stanie końcowym. To może być problematyczne.)

Wreszcie, zgadzam się, że metoda statyczna fabryki jest dobra alternatywa dla tego podejścia.

+0

Czy to naprawdę odpowiada na wiadomość e-mail dotyczącą drugiego konstruktora? – RonU

+3

* odebrać pocztę * ??? –

+0

@RonU - IMO, moja odpowiedź bezpośrednio odnosi się do pytania OP. Jeśli się nie zgadzasz, proszę wyjaśnij dlaczego. –

5

można wdrożyć „domyślnego konstruktora” jako statycznej metody fabryki:

public class Foo { 
    public static Foo createFooWithDefaultBar() { 
    Bar b = new Bar(); 
    b.setSomeData(); 
    b.doSomethingElse(); 
    return new Foo(b); 
    } 
    public Foo(Bar b) { 
    // ... 
    } 
} 
-1

Jak mówi, to wezwanie do tego() musi być pierwszą rzeczą zdarzyć się w konstruktora. Czy istnieje jakiś powód, dla którego to nie zadziałałoby?

public class Foo { 
    public Foo() { 
    this(new Bar()); 
    Bar b = getBar(); 
    b.setSomeData(); 
    b.doSomethingElse(); 
    } 
    public Foo(Bar b) { 
    // ... 
    } 
} 
+0

To może działać, ale to styk brzydki :-) –

+0

żaden argument o tym. Dla mnie te sytuacje często zamieniają się w moje pytanie, do-ja-naprawdę-chcę-tego-konstruktora, i zazwyczaj odpowiedź brzmi nie, ponieważ myślę, że to pachnie źle. Wolałbym, aby instantiator przeszedł w pełni skonfigurowany pasek (drugi konstruktor) i ruszył dalej. – RonU

+2

To nie zadziała, ponieważ 'Foo (Bar b)' może zrobić kilka operacji z 'B', które mają się wydarzyć po inicjalizacji' B' – yegor256

Powiązane problemy