Eu tenho uma classe base abstrata e quero declarar um campo ou uma propriedade que terá um valor diferente em cada classe que herda dessa classe pai.
Eu quero defini-lo na classe base para que eu possa referenciá-lo em um método de classe base - por exemplo, substituindo ToString para dizer "Este objeto é do tipo propriedade / campo ". Eu tenho três maneiras que eu posso ver para fazer isso, mas eu estava pensando - qual é a melhor ou mais aceita maneira de fazer isso? Pergunta para iniciantes, desculpe.
Opção 1:
use uma propriedade abstrata e substitua-a nas classes herdadas. Isso se beneficia ao ser aplicado (é necessário substituí-lo) e é limpo. Mas, parece um pouco errado retornar um valor de código rígido em vez de encapsular um campo e são algumas linhas de código em vez de apenas. Eu também tenho que declarar um corpo como "definido", mas isso é menos importante (e provavelmente existe uma maneira de evitar aquilo de que não estou ciente).
abstract class Father
{
abstract public int MyInt { get; set;}
}
class Son : Father
{
public override int MyInt
{
get { return 1; }
set { }
}
}
Opção 2
Posso declarar um campo público (ou um campo protegido) e substituí-lo explicitamente na classe herdada. O exemplo abaixo me dará um aviso para usar "novo" e provavelmente posso fazer isso, mas parece errado e quebra o polimorfismo, que era o ponto principal. Não parece uma boa ideia ...
abstract class Mother
{
public int MyInt = 0;
}
class Daughter : Mother
{
public int MyInt = 1;
}
Opção 3
Eu posso usar um campo protegido e definir o valor no construtor. Isso parece bem arrumado, mas depende de eu garantir que o construtor sempre defina isso e com vários construtores sobrecarregados, sempre haja uma chance de que algum caminho de código não defina o valor.
abstract class Aunt
{
protected int MyInt;
}
class Niece : Aunt
{
public Niece()
{
MyInt = 1;
}
}
É um pouco de uma questão teórica e acho que a resposta deve ser a opção 1, pois é a única opção segura, mas estou começando a entender o C # e queria perguntar isso a pessoas com mais experiência.
fonte
Respostas:
Das três soluções, apenas a opção 1 é polimórfica .
Os campos por si só não podem ser substituídos. É exatamente por isso que a opção 2 retorna o novo aviso de palavra-chave.
A solução para o aviso não é anexar a palavra-chave “nova”, mas implementar a Opção 1.
Se você precisa que seu campo seja polimórfico, é necessário envolvê-lo em uma Propriedade.
A opção 3 é válida se você não precisar de comportamento polimórfico. Você deve se lembrar, porém, que quando em tempo de execução a propriedade MyInt é acessada, a classe derivada não tem controle sobre o valor retornado. A classe base por si só é capaz de retornar esse valor.
É assim que uma implementação verdadeiramente polimórfica de sua propriedade pode parecer, permitindo que as classes derivadas estejam no controle .
fonte
A opção 2 não é iniciada - você não pode substituir os campos, só pode ocultá- los.
Pessoalmente, eu optaria pela opção 1 todas as vezes. Eu tento manter os campos privados o tempo todo. Isso se você realmente precisar substituir a propriedade, é claro. Outra opção é ter uma propriedade somente leitura na classe base, que é configurada a partir de um parâmetro do construtor:
Essa é provavelmente a abordagem mais apropriada se o valor não mudar ao longo da vida útil da instância.
fonte
a opção 2 é uma má ideia. Isso resultará em algo chamado sombreamento; Basicamente, você tem dois membros "MyInt" diferentes, um na mãe e outro na filha. O problema é que os métodos implementados na mãe farão referência ao "MyInt" da mãe, enquanto os métodos implementados na filha farão referência ao "MyInt" da filha. isso pode causar sérios problemas de legibilidade e confusão posteriormente.
Pessoalmente, acho que a melhor opção é 3; porque fornece um valor centralizado claro e pode ser referenciado internamente por crianças sem o incômodo de definir seus próprios campos - que é o problema da opção 1.
fonte
Você poderia fazer isso
virtual permite que você obtenha uma propriedade de um corpo que faz algo e ainda permite que as subclasses a substituam.
fonte
Você pode definir algo como isto:
Ao definir o valor como somente leitura, ele garante que o valor dessa classe permaneça inalterado durante a vida útil do objeto.
Suponho que a próxima pergunta seja: por que você precisa disso?
fonte
Se você está construindo uma classe e deseja que exista um valor base para a propriedade, use a
virtual
palavra - chave na classe base. Isso permite que você substitua opcionalmente a propriedade.Usando seu exemplo acima:
Em um programa:
fonte
Eu iria com a opção 3, mas teria um método setMyInt abstrato que as subclasses são forçadas a implementar. Dessa forma, você não terá o problema de uma classe derivada esquecer de defini-la no construtor.
A propósito, com a opção um, se você não especificar set; na propriedade abstrata da classe base, a classe derivada não precisará implementá-la.
fonte
Você pode usar a opção 3 se modificar sua classe base abstrata para exigir o valor da propriedade no construtor, não perderá nenhum caminho. Eu realmente consideraria essa opção.
Obviamente, você ainda tem a opção de tornar o campo privado e, dependendo da necessidade, expor um getter de propriedade pública ou protegida.
fonte
Eu fiz isso...
Dessa forma, você ainda pode usar campos.
fonte
O exemplo de implementação quando você deseja ter uma classe abstrata com implementação. As subclasses devem:
Nesse caso, as propriedades necessárias para a implementação não devem estar disponíveis para uso, exceto para a classe abstrata e sua própria subclasse.
fonte