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.)