Sto sfruttando l'ereditarietà o questo è esattamente ciò per cui è qui?

0

Ho una classe chiamata BagItem e un'altra classe chiamata EquipmentItem entrambe le classi sono esatte lo stesso nei metodi, ecc, con l'eccezione di 1 proprietà.

BagItem have:

public InventoryBagType BagType { get; private set; }

EquipmentItem have:

public InventoryEquipmentType EquipmentType { get; private set; }

Credo che dovrei menzionare, BagItem si riferisce agli oggetti che sono nella borsa del personaggio mentre EquipmentItem avrei dovuto probabilmente chiamarlo EquippedItem che si riferisce all'articolo attualmente equipaggiato dal personaggio.

Da quelle 2 classi ho altre classi che ereditano dall'una o dall'altra.

Quindi da EquipmentItem ad esempio ho CombatEquipmentItem che eredita da EquipmentItem e CombatEquipmentItem hanno solo una proprietà extra.

public CombatEquipmentType SlotType { get; private set; }

A questo punto non so se CombatEquipmentItem avrà o meno più proprietà o metodi, né se né BagItemEquipmentItem .

Stavo considerando di creare ancora un'altra classe InventoryItem che terrebbe tutte le voci comuni da BagItem e EquipmentItem e che erediterebbero da esso e dal suo turno CombatEquipmentItem da esso.

Devo eliminare BagItem e EquipmentItem per InventoryItem e mantenere entrambe le proprietà lì e impostare uno o l'altro come null in base all'elemento ed ereditare qualcos'altro da esso o dovrei andare avanti con un'altra classe o il mio design è cattivo dall'inizio e come avrebbe dovuto essere scritto come?

    
posta Prix 27.10.2015 - 16:09
fonte

2 risposte

6

Quando prendo un oggetto da un sacchetto e lo tengo in mano (dotandolo) ... cambio il tipo dell'oggetto? Devo modificare le proprietà dell'articolo?

No, quindi questo non ha senso nel mondo reale (o in un gioco, dal POV del giocatore), il che significa che non stai modellando nulla nel dominio del problema.

Forse stiamo modellando qualcosa nel dominio della soluzione, invece? Anche qui ci sono dei problemi:

  • il tuo BagItem non sa a che tipo di slot può essere equipaggiato. Quindi, come puoi prendere qualcosa dalla borsa e equipaggiarlo?
  • perché il tuo articolo deve sapere che tipo di borsa è conservata in ogni caso? Sicuramente sai quale borsa reale è dentro, perché l'hai trovato in qualche modo, presumibilmente guardando in una borsa. Pertanto, tali informazioni sono già disponibili nel contesto esterno all'elemento.

Riepilogo: nessuno di questi tipi sembra modellare qualcosa di utile, ma omette alcune cose di cui hai chiaramente bisogno. Basta usare un singolo tipo e aggiungere funzionalità come realmente necessario.

    
risposta data 27.10.2015 - 16:45
fonte
5

L'ereditarietà è uno strumento. Se ti semplifica la vita, usalo. Il problema è che non è sempre chiaro quando usarlo e quando usare la composizione.

Considera: che cosa puoi ereditare?

1) Dati: in linguaggi simili a C ++, puoi ereditare i dati dal tuo oggetto genitore e accedervi.

2) Interfaccia: questo è solitamente il motivo per cui si desidera ereditare. È ciò che Java ha la nozione di interfacce.

3) Codice: se il tuo genitore definisce una versione "predefinita" del codice che desideri, ottieni il codice (e l'interfaccia).

Quindi, considera come usi un oggetto.

Potresti voler utilizzare l'ereditarietà perché tutti i tuoi articoli hanno lo stesso tipo di dati: posizione, peso, mobilità, stato. Avere tutti i tuoi oggetti ereditati da una classe base con quegli attributi ti renderà facile pensare su tutti gli articoli. Questa è una buona ragione per usare l'ereditarietà: dati comuni che hanno tutti gli elementi.

  class BaseItem {
      string location;  //What room is the item in?
      int weight;       // for encumbrance
      bool mobility;    // can I move this item?
      bool status;      // dead or alive
  }

  class ArmorItem : public Item {
      int damageReduction;  // ... plus all the other attributes above
  }

  class WeaponItem : public Item {
      int damage; // how much damage this does
  }

Considera il prossimo esempio: Lo stai usando in loop dove fai sempre la stessa cosa? (Questo di solito è l'ereditarietà dell'interfaccia con il polimorfismo e la ragione per usare l'ereditarietà). In questo caso, tutti gli elementi ereditano l'interfaccia della classe base:

 for item in inventory :
      item.print_description()    # All different item types may describe themselves differently

  for item in inventory :
       damage_reduction += item.damage_reducer(CURRENT_DAMAGE_TYPE)   # Some items do nothing, armor items reduce damage

In sostanza, se si fa sempre la stessa cosa a tutti i tipi di elementi diversi e si desiderano comportamenti diversi per i diversi tipi di elementi, l'ereditarietà ha senso.

Gli esempi sopra sono di solito i modi canonici per usare l'ereditarietà. Occasionalmente, puoi usare l'ereditarietà per darti qualcosa dove quasi tutto ciò che vuoi è da qualche parte, ma non tutto. Ad esempio, si desidera tutta l'interfaccia di una classe numerica complessa, ma si desidera solo un altro metodo che fornisce l'ampiezza del complesso. È possibile ereditare dal complesso (mycomplex) e aggiungere un nuovo metodo. Ottieni tutta l'interfaccia, il codice e i dati dal complesso, ma aumenta la classe con qualcosa che desideri.

Altre discussioni sull'ereditarietà:
principio di sostituzione di liskov Preferisci la composizione all'ereditarietà

Le persone sono nervose sull'ereditarietà perché possono rendere il codice molto difficile mantenere. Ma se puoi usare l'ereditarietà perché rende il tuo codice più semplice, non è questo il significato degli strumenti?

    
risposta data 28.10.2015 - 00:29
fonte

Leggi altre domande sui tag