Come sovrascrivo il Tipo di membri in una classe base dalla classe derivata?

3

Ho due classi che si conoscono in una relazione molti-a-molti. Ora voglio avere due classi aggiuntive che ereditano dalle classi esistenti. L'associazione tra le classi ereditate dovrebbe rimanere.

Esempio:

Supponiamo che tu abbia un Vehicle

public class Vehicle{ }

E hai Tire s

public class Tire { }

Ora vuoi che Vehicle abbia molti Tire s

public class Vehicle
{
    public Tire[] Tires { get; set; }
}

È fantastico! Ma un Truck s Tire s sono significativamente diversi dagli altri Vehicle s .. Sono più grandi, hanno picchi (grandi borchie in metallo Ramones!), Sono fatti di polimeri dell'era spaziale (plausibilmente dallo spazio-esterno) e riempito con nuovi gas (non è freddo al neon?).

public class TruckTire : Tire { }

Ma ecco lo sfregamento ... il mio Truck ora ha solo% normaleTire s se eredita da Vehicle ...

public class Truck : Vehicle { }

Cruciale del problema & domanda:

Quindi ... Come faccio a fare in modo che quando le persone accedono a Truck.Tires torni qualcosa che è stato lanciato come TruckTire[] invece del normale vecchio Tire[] quando la proprietà Tires è definita nella base classe con un tipo di Tire[] non TruckTire[] ? Sì, le istanze in fase di esecuzione potrebbero essere TruckTire s, ma ciò richiederebbe un cast da utilizzare come tale ...

    
posta Marc 15.05.2015 - 20:03
fonte

2 risposte

4

TruckTire è un Tire tutto a posto quindi l'ereditarietà è appropriata qui. Truck tuttavia non può utilizzare Tire s, solo TruckTire s. Questo possiamo ottenere introducendo alcuni generici elementari. Se il programma richiede tipi aggiuntivi, ad esempio Tractor e TractorTire , la soluzione potrebbe essere facilmente estesa a questo.

public class Vehicle<T extends Tire> {

    private T[] tires;

    public T[] getTires() {
        return tires;
    }

    public void setTires(T[] tires) {
        this.tires = tires;
    }

    @Override
    public String toString() {
        if (tires == null || tires.length <= 0) {
            return String.format("%s has no tires", this.getClass().getSimpleName());
        } else {
            return String.format("%s has %d tires of type %s", this.getClass().getSimpleName(),
                    tires.length, tires[0].toString());
        }
    }
}

public class Truck<T extends TruckTire> extends Vehicle<T> {
}

public class Tire {

    @Override
    public String toString() {
        return this.getClass().getSimpleName();
    }
}

public class TruckTire extends Tire {
}

public class App {

    public static void main(String[] args) {
        // vehicle
        Vehicle<Tire> vehicle = new Vehicle<>();
        System.out.println(vehicle);
        Tire[] tires = {new Tire(), new Tire(), new Tire(), new Tire()};
        vehicle.setTires(tires);
        System.out.println(vehicle);

        // truck
        Truck<TruckTire> truck = new Truck<>();
        System.out.println(truck);
        TruckTire[] truckTires = {new TruckTire(), new TruckTire(), new TruckTire(), new TruckTire()};
        truck.setTires(truckTires);
        System.out.println(truck);
    }
}

Uscita console:

Vehicle has no tires
Vehicle has 4 tires of type Tire
Truck has no tires
Truck has 4 tires of type TruckTire
    
risposta data 16.05.2015 - 14:38
fonte
2

In base all'aggiornamento del 2015-05-18.

TruckTire dovrebbe essere una sottoclasse privata di Tiro. Tyre dovrebbe contenere l'interfaccia utilizzata da altre classi di clienti (Truck, Car) e TruckTire incapsula il comportamento. L'interfaccia del Truck con TruckTire è la stessa che l'interfaccia di Car è per CarTire. Li conoscono tutti come pneumatici. Utilizza il modello di strategia per Tyre.

    
risposta data 16.05.2015 - 19:43
fonte

Leggi altre domande sui tag