2010-10-07 6 views
5

C'est ce que je suis en train de faire (en Java 1.6):Comment implémenter le wrapping constructeur en Java?

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

compilateur dit:

call to this must be first statement in constructor 

Y at-il solution de contournement?

Répondre

17

Vous devez mettre en œuvre comme ceci:

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

La méthode makeBar doit être statique, puisque l'objet correspondant à this n'est pas disponible au moment où vous appelez la méthode.

Par ailleurs, cette approche a l'avantage fait passer un objet Bar complètement initialisé à la Foo(Bar). (@RonU note que son approche ne fonctionne pas. Ce signifie bien sûr que son constructeur Foo(Bar) ne peut pas présumer que son argument Foo est dans son état final. Cela peut être problématique.)

Enfin, je suis d'accord qu'une méthode d'usine statique une bonne alternative à cette approche.

+0

Est-ce que cela répond vraiment au courrier sur le second constructeur? – RonU

+3

* répondez au mail * ??? –

+0

@RONU - OMI, ma réponse répond directement à la question du PO. Si vous n'êtes pas d'accord, veuillez expliquer pourquoi. –

5

Vous pouvez mettre en œuvre le « constructeur par défaut » comme méthode d'usine statique:

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

Comme il est dit, un appel à cette() doit être la première chose à se produire dans un constructeur. Y at-il une raison pour que cela ne fonctionne pas?

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

Cela pourrait fonctionner, mais c'est butt-moche :-) –

+0

Aucun argument à ce sujet. Pour moi, ces situations se transforment souvent en un constructeur qui me demande de faire vraiment ce que je veux, et généralement la réponse est non, car je pense que cela sent mauvais. Je préfère que l'instantiateur passe dans une barre entièrement configurée (second constructeur) et continue. – RonU

+2

Cela ne fonctionnera pas parce que 'Foo (Bar b)' peut faire des opérations avec 'b', ce qui doit arriver après l'initialisation de' b' – yegor256