Pergunta

Eu tenho uma estrutura de classe para um jogo de dramatização que se parece com isso ...

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; }
}

Basicamente, estou tentando forçar todos os tipos derivados a incluir uma propriedade "nome". Esse é o melhor jeito de fazer isso? Sei que posso remover "abstrato" do item.name e, em seguida, remover as propriedades de "nome" excedentes em armadura e capacete. Se eu fizer isso, o código parece um pouco mais limpo, mas posso esquecer de definir a base. Nome nessas classes derivadas.

Alguém poderia ajudar a me mostrar a melhor maneira de fazer isso?

EDIT: Desculpe, deixe -me esclarecer uma pergunta um pouco mais. Eu quero ter certeza de 2 coisas. 1) A propriedade de nome existe em todas as classes derivadas 2) A propriedade de nome não é nula ou vazia

Basicamente, quero forçar qualquer classe que deriva do item (e não seja abstrata) a ter um valor para o nome.

Foi útil?

Solução

Parece que você está preocupado com a inicialização de propriedades?

Mas eu poderia esquecer de definir a base.name nessas classes derivadas.

Uma maneira pela qual você pode forçar o nome da propriedade a ser configurada é incluir este setter no seu construtor de classe base como:

public class MyBaseClass
{
    private string _name;

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

Então tudo o que deriva do mybaseClass deve satisfazer esse construtor:

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

    }
}

Então você também pode fazer a propriedade:

  • resumo para garantir que exista em cada classe derivada com sua própria implementação
  • Virtual para fornecer uma implementação básica e tudo para ser substituído.

Não vou me aventurar se o exposto acima é um bom design, mas funcionaria para garantir que todas as classes derivadas tenham uma propriedade de nome válida quando instanciadas.

Outra abordagem, como sugerem outras respostas, é implementar uma propriedade virtual que lança uma exceção em sua implementação básica.

Outras dicas

Você só precisa definir Name na classe base e não precisa especificá -la como abstrata. Ainda estará disponível como uma propriedade em todas as classes derivadas.

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

public abstract class Armor : Item
{ }

public class Helmet : Armor
{ }

Se eu fizer isso, o código parece um pouco mais limpo, mas posso esquecer de definir a base. Nome nessas classes derivadas.

Então o nome do objeto acabará sendo algo bobo.

Melhor ainda, tenha name comece como null. Em seguida, você terá uma exceção se esquecer de inicializar o nome, mas alguém tenta usá -lo e saberá que terá que corrigi -lo.

Mike está certo que, se você deseja apenas usar a propriedade "Nome" em todos os objetos derivados, não precisa ser um abstrato marcado como é herdado.

Se você deseja apenas forçar o fato de que, quando os itens são criados, um nome é definitivamente definido, você pode forçá-lo a ocultar o construtor de parâmetro zero e expor um construtor que aceita o nome.

Dê uma olhada neste código:

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() {}
}

As definições acima significam que:

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

Isso força que qualquer instância das classes deve definir o nome no momento da criação. Uma solução possível de qualquer maneira ...

Fazer nome um IE virtual. public virtual Name {get; set; } acessador pode ser usado na classe de itens? Desde que Helmment e Armour descem da aula de itens. Isso aplicaria que eles devem ser substituídos ...

Espero que isso ajude, cumprimentos, Tom.

Então, depende do que você quer fazer ...

Tornar a classe abstrata força todas as subclasses a implementar a classe (e suas funções abstratas, etc.), mas se você deseja que uma função tenha uma funcionalidade básica com a possibilidade de substituir a função, sugerirei que não faça a classe Resumo e fazendo a função específica virtual, portanto, quando a função virtual não está sendo substituída, e a função base será chamada.

E sempre há opções para criar uma "nova" propriedades com o mesmo nome, mas não acho que seja uma boa prática.

espero que ajude.

Eu acho que você ainda pode tornar a propriedade virtual em uma classe abstrata, portanto, isso deve resolver seu problema.

Você pode definir o valor para algo específico na classe abstrata base, aqui um exemplo:

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
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top