Como forçar uma classe derivada a incluir certas propriedades com valor padrão
-
23-09-2019 - |
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.
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
}