Domanda

ho una struttura di classe per un gioco di ruolo che assomiglia a questo ...

public abstract class Item
{
   public abstract string Name { get; set; }
}

public abstract class Armor : Item
{
   public override string Name { get; set; }
}

public class Helmet : Armor
{
   public override string Name { get; set; }
}

In sostanza, sto cercando di forzare ogni tipo derivato per includere un "Nome" di proprietà. È questo il modo migliore per farlo? So di poter rimuovere "astratto" da Item.Name e quindi rimuovere i sovrascritto proprietà "Nome" in armatura e casco. Se faccio che il codice sembra un po 'più pulita ma potrei dimenticare di impostare il base.Name in queste classi derivate.

Qualcuno potrebbe aiutarmi a mostrare il modo migliore per farlo?

EDIT: Siamo spiacenti, vorrei chiarire la mia domanda un po 'di più. Voglio fare in modo di 2 cose. 1) Nome esiste in tutte le classi derivate 2) proprietà Name non è nullo o vuoto

Io fondamentalmente voglio forzare qualsiasi classe che deriva dalla voce (e non è astratta) per avere un valore per il nome.

È stato utile?

Soluzione

Sembra che siete preoccupati per l'inizializzazione proprietà?

  

ma potrei dimenticare di impostare la   base.Name in queste classi derivate.

Un modo la si può forzare la proprietà Name da impostare è quello di includere questo setter nel costruttore della classe base in questo modo:

public class MyBaseClass
{
    private string _name;

    public MyBaseClass(string name)
    {
        _name = name;
    }
}

Quindi tutto ciò che deriva da MyBaseClass deve soddisfare quel costruttore:

public class MyDerivedClass
{
    public MyDerivedClass(string name) : base(name)
    {

    }
}

Poi si può anche fare la proprietà sia:

  • astratta per garantire che esiste in ogni classe derivata con la propria implementazione
  • virtuale per fornire un'implementazione base e tutto per essere sovrascritta.

Non ho intenzione di avventurarsi se quanto sopra è un buon design, ma sarebbe lavorare per garantire che tutte le classi derivate hanno una proprietà nome valido quando un'istanza.

Un altro approccio, come altre risposte suggeriscono, è quello di implementare una proprietà virtuale che genera un'eccezione nella sua implementazione di base.

Altri suggerimenti

Hai solo bisogno di definire Name nella classe base, e non c'è bisogno di specificarlo come astratta. Sarà ancora disponibile come proprietà in tutte le classi derivate.

public abstract class Item
{
   public string Name { get; set; }
}

public abstract class Armor : Item
{ }

public class Helmet : Armor
{ }
  

Se faccio che il codice sembra un po 'più pulita ma potrei dimenticare di impostare il base.Name in queste classi derivate.

Poi il nome dell'oggetto sarà solo finiscono per essere qualcosa di stupido.

Meglio ancora, hanno name iniziare come null. Poi si otterrà un'eccezione se si dimentica di inizializzare il nome, ma qualcuno cerca di usarlo, e ti sai che devi risolvere il problema.

Mike è giusto che se si desidera utilizzare la proprietà "Nome" su tutti gli oggetti derivati, non è necessario che sia contrassegnato astratto a tutti come è ereditato.

Se si vuole forzare solo il fatto che quando si creano elementi, un nome è sicuramente impostato, si potrebbe forzare attraverso nasconde il costruttore zero parametri ed esponendo un costruttore che accetta il nome.

Date un'occhiata a questo codice:

public class Item
{
   public string Name { get; set; }

   public Item(string name)
   {
       this.Name = name;
   }

   protected Item() {}
}

public class Armor : Item
{   
   public Armor(string name) : base(name) {}
   protected Armor() {}
}

public class Helmet : Armor
{   
   public Helmet(string name) : base(name) {}
   protected Helmet() {}
}

Le definizioni di cui sopra significano che:

Helmet myHelmet = new Helmet(); //will not build
Helmet myHelmet = new Helmet("Some Fancy Helmet Name"); //will build

Armor myArmor  = new Armor (); //will not build
Armor myArmor  = new Armor ("Some Fancy Armor Name"); //will build

Item myItem = new Item (); //will not build
Item myItem = new Item("Some Fancy Item Name"); //will build

In questo modo che qualsiasi istanza delle classi deve definire il nome al momento della creazione. Una possibile soluzione in ogni caso ...

Sarebbe fare un nome cioè virtuale. di accesso public virtual Name {get; set; } essere utilizzato nella classe dell'oggetto? Dal momento che helment e armatura scendere dalla classe Item. Sarebbe valere che devono essere ridefiniti ...

Spero che questo aiuti, I migliori saluti, Tom.

quindi dipende da cosa si vuole fare ...

making classe forze astratte tutte le sottoclassi per implementare la classe (e le sue funzioni astratte, etc.), ma se volete una funzione per avere una funzionalità di base con la possibilità di ignorare la funzione allora io non suggeriscono rendendo la classe astratta e rendendo la specifica funzione virtuale invece, così quando non viene sovrascritto la funzione virtuale, e verrà chiamato funzione base.

E c'è sempre le opzioni per la creazione di un "nuovo" gli oggetti con lo stesso nome, ma non credo che sia una buona pratica.

speranza che aiuta.

Credo che si può ancora fare la proprietà virtuale all'interno di una classe astratta, così che dovrebbe risolvere il problema.

È possibile impostare il valore a qualcosa di specifico nella classe astratta di base, qui un esempio:

public abstract class Item
{
   public virtual string Name 
   { 
         get {return m_strName;} 
         set {m_strName = value;}
   }

public abstract class Armor : Item
{
   public override string Name { get; set; } // if you want to override it 
}

public class Helmet : Armor
{
   public override string Name { get; set; } // if you want to override it
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top