2010-05-17 11 views
5

Próbuję utworzyć klasę z wieloma parametrami, używając raczej wzorca Builder niż konstruktorów teleskopowych. Robię to w sposób opisany przez Efektywną Javę Joshua Blocha, z prywatnym konstruktorem na otaczającej klasie i publiczną statyczną klasą Builder. Klasa Builder zapewnia, że ​​obiekt jest w stanie spójnym przed wywołaniem funkcji build(), w którym to momencie deleguje konstrukcję otaczającego obiektu do prywatnego konstruktora. Tak więc Konstruktor Java z typowymi granicami

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

    } 

} 
Następnie chcę dodać granice typu do niektórych zmiennych, a więc trzeba parametrize definicji klasy. Chcę, aby granice klasy Foo były takie same jak w klasie 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); 
     } 

    } 

} 

To kompiluje grzywny, ale kompilator pozwala mi robić rzeczy, czuję, że powinienem być błędy kompilatora. Na przykład.

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

Oto argument jednostki nie jest Unit<Acceleration> ale Unit<Length>, ale wciąż jest akceptowane przez kompilator.

Co ja tu robię źle? Chcę podczas kompilacji upewnić się, że typy jednostek pasują poprawnie.

Odpowiedz

6

units powinien zwrócić Builder<Q>, a nie niezgrupowany Builder.

+0

Dziękuję, nie myślałem bardzo wyraźnie w ten szacunek. – I82Much

0

Chociaż punkt @ Daniela jest ważny, błąd w kodzie jest wykryty przynajmniej przez Eclipse. Oczywiście, twoja definicja Quantity, Unit i METER jest prawdopodobnie różni się od uproszczonym siekać ułożyła:

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

komunikat o błędzie jest:

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

Interesujące. Używałem NetBeans, który nie narzekał. Hierarchia jednostek itp., Której używam, pochodzi z JSR 275 (http://download.java.net/maven/2/net/java/dev/jsr-275/jsr-275/1.0-beta-2/) i JScience (http://jscience.org/) – I82Much

+2

Powinieneś dostać ten błąd nawet w NetBeans ... jeśli nie, to bardzo zły błąd. Różnica w oryginalnym kodzie jest taka, jeśli masz właściwość pośrednią: nowy Foo.Builder (). Sera (GOUDA) .jednostki (Unit.METER), gdzie metoda "sera" zwraca Builder not Builder . – Cowan

Powiązane problemy