Come già sottolineato nei commenti e nelle risposte: Tutto dipende da cosa si sta cercando di modello lì.
Ma prima di tutto, per quanto riguarda l'intenzione che lei ha citato:
Quindi sono solo la creazione di loro in caso che io abbia mai bisogno di utilizzare un instanceof istruzione condizionale.
Fare attenzione. Dovresti evitare di modellare il diverso comportamento degli oggetti a seconda del loro tipo. Qui, non importa se le informazioni tipo è
- implicitamente disponibili via
instanceof
controlli
- esplicitamente tramite un metodo come
boolean isMotorCycle()
, come suggerito in un commento
- esplicitamente via qualcosa come un
enum Type { ... }
e un switch
sopra Il tipo.
tutti soffrono dello stesso problema: Quando si aggiunge una nuova classe/tipo di gerarchia, poi si deve adottare e aggiornare tutti luoghi in cui è stato chiesto spiegazioni informazioni sul tipo. Questo potrebbe diventare un incubo per la manutenzione.
Lì sono usi legittimi per i controlli di tipo. Ma quando si finisce con la scrittura di codice che fa di frequente controlli come questo
void recharge(Vehicle v) {
if (v instanceof ElectricCar) ((ElectricCar)v).attachPlug();
if (v instanceof GasolineCar) ((GasolineCar)v).fillFuel();
if (v instanceof Bike) ((Bike)v).getDriver().takeRest();
...
}
allora questa è una forte indicazione che qualcosa non va con la gerarchia. Potrebbe essere che la classe base, Vehicle
, non sia semplicemente abbastanza potente. Nell'esempio sopra, si potrebbe quindi considerare di utilizzare il metodo recharge()
nella classe Vehicle
e semplicemente chiamarlo, basandosi sull'implementazione polimorfica.
Potrebbe, nel caso peggiore, anche che i concetti che si sta tentando di modellare siano semplicemente troppo estranei per essere combinati in una singola gerarchia.
Lei ha detto che si vuole fare il rilevamento delle collisioni per questi oggetti. Sembra che ti stia già avvicinando a una soluzione come questa:
class Bike extends Vehicle {
@Override
void collideWith(Vehicle other) {
if (other instanceof Car) collideWithCar((Car)other);
if (other instanceof Segway) collideWithSegway((Segway)other);
...
}
}
Ci sono soluzioni più eleganti per questo. Potresti voler leggere il problema relativo a Double Dispatch e forse dare un'occhiata allo Strategy Pattern.
Più in generale, riguardo alla domanda se avete "troppe classi", ci sono alcune regole generali per pollice.
Uno di questi è Interface Segration Principle, in cui si afferma che è necessario creare interfacce client specifiche del serval, invece di un'interfaccia grande che fa tutto e quindi combina metodi altrimenti non correlati. Quindi non hai "troppe classi", purché ognuna di esse abbia uno scopo. Si potrebbe chiedere a te stesso:
- che dovrà distinguere tra un
GasolineCar
ed un ElectricCar
?
- Chi dovrà occuparsi solo di una di queste interfacce?
- Quando entrambi estendere la stessa classe di base: Chi sarà in grado di utilizzare la classe di base (o saranno tutti devono conoscere l'implementazione specifica comunque?)
Sono interessato in un modo che si intende utilizzare queste classi. – SMA
tutto dipende da come li userete. Niente di sbagliato con la tua struttura finora. E potresti non solo usarlo per esempio ma, ad esempio, per metodi come boolean needsPetrol() ... canHavePassengers() che implementerai nelle sottoclassi invece di usare chain of if instanceof statements. – Zielu
Cosa stai cercando di fare? – nom