Per iniziare, questa è più una questione di buone pratiche che altro.
Introduzione all'ambiente
Ho me stesso una classe astratta. Chiamiamo questa classe Item . Ho anche un'altra classe astratta, la chiameremo Container . La classe Container eredita la classe Item .
Ecco il mio dilemma: sto cercando di disegnare correttamente le porzioni OOP di esso e sto avendo un po 'di problemi a causa del mio desiderio di astrarre il più possibile, pur continuando a essere gestibile e comprensibile codice.
Iniziamo con un codice:
public abstract class Item
{
private Guid _Guid;
private float _Weight;
public Guid Guid { get { return _Guid; } set { _Guid = value; } }
public float Weight { get { return _Weight; } set { _Weight = value; } }
public virtual ItemType ItemType { get { return ItemType.None; } }
}
public abstract class Container : Item
{
private float _MaxWeight;
private List<Item> _Items;
public List<Item> Items { get { return _Items; } }
public float MaxWeight { get { return _MaxWeight; } set { _MaxWeight = value; } }
public abstract ContainerType ContainerType { get; }
public sealed override ItemType ItemType { get { return ItemType.Container; } }
}
Quindi, con questo codice l'intenzione è per un Container di poter essere trattato come Item , con alcune eccezioni. (Il contenitore avrà proprietà aggiuntive, ecc.)
Il problema è che non tutti gli oggetti Item possono essere aggiunti a Container . Infatti, solo gli oggetti Container che hanno oggetti Container.MaxWeight o non% Container Item possono essere aggiunti.
A partire da ora, questa restrizione non può essere inserita. Il mio primo pensiero è stato quello di creare un ItemCollection nella classe Container , che essenzialmente conserverebbe tutti gli oggetti Item al suo interno. Questo mi permetterebbe di implementare il mio metodo ItemCollection.Add che eseguirà questo filtro.
Il problema entra in gioco quando introduco la mia terza classe. Chiamiamolo a Backpack . Questo eredita Container e appare come segue:
public class Backpack : Container
{
public sealed override ContainerType ContainerType { get { return ContainerType.Backpack; } }
}
Attenzione: il Backpack (come lo chiamiamo) sarà in grado di contenere% oggetti% co_de, o% oggetti% co_de con un Item minore in essi.
Questo significa anche che potrei avere altre classi (usiamo, ad esempio, Container ) che erediterà anche Container.MaxWeight , ma che non può contenere altri oggetti Pouch .
Infine, potrebbero esserci anche classi aggiuntive che non possono contenere oggetti Container , ma solo oggetti Container trattenuti. (Vedi, ad esempio, Item .)
/// <summary>
/// Represents a collection of <see cref="Container"/> objects owned by an <see cref="Actor"/>.
/// </summary>
public class Inventory : Container
{
public sealed override ContainerType ContainerType { get { return ContainerType.Inventory; } }
}
Dichiarazioni della domanda
È questo il modo migliore per farlo? Devo implementare il Container come volevo? Che dire degli oggetti Inventory che possono contenere solo altri oggetti ItemCollection ?
Devo usare Container per indicare che questo oggetto può contenere solo altri oggetti Container ? Dovrei invece usare il valore ContainerType.Inventory su di esso? (Qualsiasi oggetto che può contenere solo oggetti Inventory non realmente ha un ContainerType.MaxWeight . Il Container e MaxWeight può contenere è determinato dalla loro idoneità.
Devo creare una classe aggiuntiva che erediti MaxWeight che possa contenere solo altri oggetti Actor , quindi ereditare Container da questo? Allo stesso modo, dovrei creare un'altra classe che eredita da Container che consente o non consente l'aggiunta di oggetti Inventory solo?
Note aggiuntive / Jargon
L'idea è di costringere i programmatori (soprattutto me) a gestire correttamente ogni Container e Item come dovrebbero essere. Il problema sta nel fatto che ci sono diversi tipi di oggetti Container . Inoltre, tieni presente che questo non è tutto del codice in questione, ma il codice aggiuntivo che ho escluso è irrilevante a questo problema. Inoltre, le due classi aggiuntive che ho citato ( Item e Container ) sono completamente concreti. Lavorerò direttamente con quelli. Voglio anche avere un'infrastruttura comune tra di loro, in modo che qualsiasi Inventory che sia un Backpack possa essere lavorato in modo generale. (Piuttosto che affidarsi alla classe concreta appropriata.)