2015-03-22 11 views
5

Mi chiedo se sto creando/suddividendo i tipi di oggetto in classi prive di significato e se c'è un modo migliore per farlo.Creazione di molti tipi/classi di oggetti solo per utilizzare l'istanza di

dire che ho ottenuto le seguenti classi (->estende la classe superiore):

Vehicle class - takes care of movement and a default speed 
-->Car class - adds passengers 
-->-->ElectricCar class - a default constructor 
-->-->GasolineCar class - a default constructor 
-->-->HybridCar class - a default constructor 
-->Motorcycle class - a default constructor 
-->Bike class - a default constructor, overrides speed 
-->Segway class - a default constructor, overrides speed 

Come si può vedere, sono per lo più costruttori di default. Pertanto, li creo solo nel caso in cui sia necessario utilizzare un'istanza condizionale dell'istruzione condizionale. La maggior parte del mio codice finisce nella classe Vehicle perché sto cercando di evitare di ripetere lo stesso codice in ogni classe. Inoltre, dovrei rendere il veicolo astratto, corretto? Non creo mai un oggetto veicolo.

OK o c'è un modo migliore per farlo?

+1

Sono interessato in un modo che si intende utilizzare queste classi. – SMA

+2

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

+0

Cosa stai cercando di fare? – nom

risposta

4

Innanzitutto, finché il codice funziona e risolve il problema, direi che è "corretto" abbastanza (quindi sì, è ok). Detto questo, alcune persone preferiscono utilizzare le interfacce anziché le classi astratte (perché è possibile implementare più interfacce ma solo estendersi direttamente da un antenato). Inoltre, se stai usando Java 8+ puoi aggiungere i metodi default alle interfacce. Altre alternative potrebbero includere una classe Vehicle ma un campo enumenum per la classe Vehicle.

+1

@Downvoter: Atleast condividi anche i tuoi pensieri, mentre downvoting. Aiuta la comunità ad andare avanti, conoscendo i propri errori –

+1

@nIcEcOw I * sempre * apprezzo il feedback costruttivo e l'opportunità di migliorare le mie risposte. –

+0

Grazie per il consiglio, penserò a un enum/stato come alternativa. Solo un altro punto e posso revocare alcune risposte lol. – SmokeyTehBear

2

Tutto si riduce alla domanda se sarà mai necessario distinguere tra ElectricCar, BenzolineCars ecc. In caso contrario, si potrebbe semplicemente mettere tutto in Veicolo o in Auto e creare oggetti Veicolo/Auto.

Se non si intende creare oggetti Veicolo, allora sì, dovrebbe essere contrassegnato come astratto.

4

Non c'è mai una cosa come "troppe lezioni" finché le tue lezioni hanno senso e servono una funzione. C'è comunque una cosa come pointless abstraction secondo me.

Se siete sicuri al 100% che si avrà solo mai utilizzare queste classi per determinare il tipo di veicolo (citazione dalla tua domanda),

mai bisogno di utilizzare un'istruzione condizionale instanceof

Quindi forse avere classi secondarie si qualifica come astrazione inutile. Usa invece un enum che descrive il tuo tipo di veicolo e vai avanti.

Se tuttavia prevedi o prevedi di utilizzare le tue sottoclassi per qualcosa di più del solo tipo, è assolutamente corretto farlo con sottoclassi e in effetti è preferibile avere un sacco di istruzioni if ​​/ else o switch nel tuo veicolo classe.

+0

Ok, fico, così come stanno le cose adesso, potrebbe essere preferibile una enum. Grazie. – SmokeyTehBear

4

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.

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?)
+0

Grazie per la risposta approfondita. L'esempio di ricarica() ha perfettamente senso ed elimina le dichiarazioni condizionali che stavo usando con entrambi gli approcci ** instanceof ** e isMotorcyle(). Ed è quello che non ho potuto avvolgere, cercando di farlo nel modo più polimorfico. È difficile per me capire chi ha raccomandato l'approccio migliore perché ci sono tanti modi per farlo, ma tutte le parti della tua risposta sembrano azzeccate. – SmokeyTehBear

Problemi correlati