2010-05-17 16 views
5

Sto tentando di creare una classe con molti parametri, utilizzando un modello di Builder piuttosto che i costruttori di telescopio. Lo sto facendo nel modo descritto da Effective Java di Joshua Bloch, con un costruttore privato nella classe che lo include e una classe Builder statica pubblica. La classe Builder assicura che l'oggetto sia in uno stato coerente prima di chiamare build(), a quel punto delega la costruzione dell'oggetto che lo include al costruttore privato. CosìPattern Java Builder con limiti di tipo generico

public class Foo { 

    // Many variables 

    private Foo(Builder b) { 
     // Use all of b's variables to initialize self 
    } 

    public static final class Builder { 

     public Builder(/* required variables */) { 

     } 

     public Builder var1(Var var) { 
      // set it 
      return this; 
     } 

     public Foo build() { 
      return new Foo(this); 
     } 

    } 

} 

poi voglio aggiungere tipo limiti ad alcune delle variabili, e quindi necessità di parametrizzare la definizione della classe. Voglio che i limiti della classe Foo siano gli stessi della classe Builder.

public class Foo<Q extends Quantity> { 

    private final Unit<Q> units; 
    // Many variables 

    private Foo(Builder<Q> b) { 
     // Use all of b's variables to initialize self 
    } 

    public static final class Builder<Q extends Quantity> { 
     private Unit<Q> units; 

     public Builder(/* required variables */) { 

     } 

     public Builder units(Unit<Q> units) { 
      this.units = units; 
      return this; 
     } 

     public Foo build() { 
      return new Foo<Q>(this); 
     } 

    } 

} 

Questo compila bene, ma il compilatore sta permettendo che io faccia cose che sento dovrebbe essere errori di compilazione. Per esempio.

public static final Foo.Builder<Acceleration> x_Body_AccelField = 
     new Foo.Builder<Acceleration>() 
     .units(SI.METER) 
     .build(); 

Qui l'argomento unità non è Unit<Acceleration> ma Unit<Length>, ma è ancora accettato dal compilatore.

Cosa sto facendo di sbagliato qui? Voglio assicurarmi al momento della compilazione che i tipi di unità corrispondano correttamente.

risposta

6

units deve restituire Builder<Q>, non un generico Builder.

+0

Grazie, non pensavo molto chiaramente nel questo riguardo. – I82Much

0

Anche se il punto @ Daniel è valido, l'errore nel codice viene comunque rilevato da Eclipse almeno. Naturalmente, la tua definizione di Quantity, Unit e METER è probabilmente diverso dal mod semplicistica ho messo insieme:

interface Quantity { 
} 
class Acceleration implements Quantity { 
} 
class Length implements Quantity { 
} 
public class Unit<Q extends Quantity> { 
    public static final Unit<Length> METER = new Unit<Length>(); 
} 

public static final Foo.Builder<Acceleration> x_Body_AccelField = 
    new Foo.Builder<Acceleration>() 
    .units(Unit.METER) // here the compiler complains 
    .build(); 

Il messaggio di errore è:

The method units(Unit<Acceleration>) in the type Foo.Builder<Acceleration> is 
not applicable for the arguments (Unit<Length>) 
+0

Interessante. Stavo usando NetBeans, che non si lamentava. La gerarchia unitaria che sto usando proviene da JSR 275 (http://download.java.net/maven/2/net/java/dev/jsr-275/jsr-275/1.0-beta-2/) e JScience (http://jscience.org/) – I82Much

+2

Si dovrebbe ottenere questo errore anche in NetBeans ... se no, questo è un bug molto brutto. La differenza nel codice originale è se si ha una proprietà intermedia: new Foo.Builder (). Cheese (GOUDA) .units (Unit.METER), dove il metodo 'cheese' restituisce Builder not Builder . – Cowan

Problemi correlati