Il seguente codice compila e funziona correttamente. Ho definito un'interfaccia Builder, quindi la classe CarBuilder è utilizzata per gestire tutto ciò che riguarda un'automobile, e la classe BusBuilder è usata per gestire qualsiasi cosa relativa ad un Bus. Auto e autobus condividono una classe astratta chiamata Veicolo. Il codice è semplice. L'output di codice volontà:Possiamo invocare dinamicamente un metodo di interfaccia Java con un parametro generico?
do something to CREATE the Car
do something to UPDATE the Car
do something to CREATE the Bus
do something to UPDATE the Bus
Ecco il codice originale che compila:
public abstract class Vehicle { }
public class Car extends Vehicle { }
public class Bus extends Vehicle { }
public interface Builder<V extends Vehicle> {
public V createVehicle(String spec);
public void updateVehicle(String spec, Vehicle vehicle);
}
public class CarBuilder implements Builder<Car> {
public Car createVehicle(String spec) {
Car car = new Car();
System.out.println("do something to CREATE the Car");
return car;
}
public void updateVehicle(String spec, Vehicle vehicle) {
Car car = (Car) vehicle;
System.out.println("do something to UPDATE the Car");
return;
}
}
public class BusBuilder implements Builder<Bus> {
public Bus createVehicle(String spec) {
Bus bus = new Bus();
System.out.println("do something to CREATE the Bus");
return bus;
}
public void updateVehicle(String spec, Vehicle vehicle) {
Bus bus = (Bus) vehicle;
System.out.println("do something to UPDATE the Bus");
return;
}
}
@Test
public void main() {
Builder<? extends Vehicle> builder = null;
Vehicle vehicle = null;
builder = new CarBuilder();
vehicle = builder.createVehicle("my original Car spec");
builder.updateVehicle("my modified Car spec", vehicle);
builder = new BusBuilder();
vehicle = builder.createVehicle("my original Bus spec");
builder.updateVehicle("my modified Bus spec", vehicle);
}
Ma, mi piacerebbe fare il mio codice ancora più fortemente tipizzato. Voglio cambiare il metodo di interfaccia,
da
public void updateVehicle(String spec, Vehicle vehicle);
a
public void updateVehicle(String spec, V vehicle);
In altre parole, ho cercato di usare generica V
posto di classe base Vehicle
nella mia firma interfaccia. Ciò impone agli implementatori di Builder
di "chiudere" il tipo di prodotto specifico (ad esempio Car
o Bus
, ma non la classe di base Vehicle
). CarBuilder
deve gestire solo un Car
; BusBuilder
dovrebbe gestire solo un Bus
.
Il codice diventa come segue:
public interface Builder<V extends Vehicle> {
public V createVehicle(String spec);
public void updateVehicle(String spec, V vehicle);
}
public class CarBuilder implements Builder<Car> {
public Car createVehicle(String spec) {
Car car = new Car();
System.out.println("do something to CREATE the Car");
return car;
}
public void updateVehicle(String spec, Car car) {
System.out.println("do something to UPDATE the Car");
return;
}
}
public class BusBuilder implements Builder<Bus> {
public Bus createVehicle(String spec) {
Bus bus = new Bus();
System.out.println("do something to CREATE the Bus");
return bus;
}
public void updateVehicle(String spec, Bus bus) {
System.out.println("do something to UPDATE the Bus");
return;
}
}
@Test
public void main() {
Builder<? extends Vehicle> builder = null;
Vehicle vehicle = null;
builder = new CarBuilder();
vehicle = builder.createVehicle("my original Car spec");
builder.updateVehicle("my modified Car spec", vehicle); <== compilation error
builder = new BusBuilder();
vehicle = builder.createVehicle("my original Bus spec");
builder.updateVehicle("my modified Bus spec", vehicle); <== compilation error
}
Due errori di compilazione - compilatore Java non permetterà questo perché "Il metodo updateVehicle (String, cattura # 3 di estende Vehicle?) Nel tipo Builder non è applicabile per gli argomenti (String, Vehicle) ".
In Java c'è un modo per fare ciò che voglio realizzare? In C# posso semplicemente digitare la mia variabile con var parola chiave, come var vehicle
anziché Vehicle vehicle
. Ho sentito che l'invocazione generica di Java è una decisione in fase di compilazione. C'è una tecnica per superare questo?
Perché il metodo di aggiornamento di un autobus o di un'auto non dovrebbe essere in quella classe? – thatidiotguy
Ha senso sì. Un Builder è più comunemente usato per creare un'istanza, non per aggiornarlo. – vptheron