// Cannot change source code
class Base
{
public virtual void Say()
{
Console.WriteLine("Called from Base.");
}
}
// Cannot change source code
class Derived : Base
{
public override void Say()
{
Console.WriteLine("Called from Derived.");
base.Say();
}
}
class SpecialDerived : Derived
{
public override void Say()
{
Console.WriteLine("Called from Special Derived.");
base.Say();
}
}
class Program
{
static void Main(string[] args)
{
SpecialDerived sd = new SpecialDerived();
sd.Say();
}
}
O resultado é:
Chamado de Special Derived.
Chamado de Derivado. / * isso não é esperado * /
Chamado da Base.
Como posso reescrever a classe SpecialDerived para que o método da classe média "Derived" não seja chamado?
UPDATE:
A razão pela qual eu quero herdar da classe Derived em vez de Base é a classe Derived contém muitas outras implementações. Como não posso fazer base.base.method()
aqui, acho que a melhor maneira é fazer o seguinte?
// Não é possível alterar o código fonte
class Derived : Base
{
public override void Say()
{
CustomSay();
base.Say();
}
protected virtual void CustomSay()
{
Console.WriteLine("Called from Derived.");
}
}
class SpecialDerived : Derived
{
/*
public override void Say()
{
Console.WriteLine("Called from Special Derived.");
base.Say();
}
*/
protected override void CustomSay()
{
Console.WriteLine("Called from Special Derived.");
}
}
c#
polymorphism
AZ.
fonte
fonte
Respostas:
Só quero adicionar isso aqui, pois as pessoas ainda retornam a essa pergunta mesmo depois de muito tempo. Claro que é uma prática ruim, mas ainda é possível (em princípio) fazer o que o autor deseja com:
fonte
Func<stuff>
vez deAction
Essa é uma prática ruim de programação e não é permitida em C #. É uma prática ruim de programação porque
Os detalhes da base geral são detalhes de implementação da base; você não deveria confiar neles. A classe base está fornecendo uma cobertura de abstração da base geral; você deve usar essa abstração, não criando um desvio para evitá-lo.
Para ilustrar um exemplo específico do ponto anterior: se permitido, esse padrão seria outra maneira de tornar o código suscetível a falhas da classe base frágil. Suponha que
C
deriva doB
qual derivaA
. Código emC
usosbase.base
para chamar um método deA
. Então o autor deB
percebe que eles colocaram muita arte em sala de aulaB
, e uma abordagem melhor é criar classe intermediáriaB2
que derivaA
eB
derivaB2
. Após essa alteração, o code inC
está chamando um métodoB2
, e não emA
, porqueC
o autor assumiu que os detalhes da implementaçãoB
, ou seja, que sua classe base direta éA
, nunca mudaria. Muitas decisões de design em C # devem atenuar a probabilidade de vários tipos de falhas na base frágil; a decisão de tornarbase.base
ilegal impede totalmente esse sabor específico desse padrão de falha.Você derivou de sua base porque gosta do que faz e deseja reutilizá-lo e ampliá-lo. Se você não gosta do que faz e quer contorná-lo em vez de trabalhar com ele, então por que você derivou disso em primeiro lugar? Você mesmo pode derivar da base geral se essa é a funcionalidade que você deseja usar e estender.
A base pode exigir certos invariantes para fins de segurança ou consistência semântica, mantidos pelos detalhes de como a base usa os métodos da base principal. Permitir que uma classe derivada da base ignore o código que mantém esses invariantes pode colocar a base em um estado inconsistente e corrompido.
fonte
Você não pode do c #. Na IL, isso é realmente suportado. Você pode fazer uma chamada não-virt para qualquer uma das suas classes principais ... mas, por favor, não faça. :)
fonte
A resposta (que eu sei que não é o que você está procurando) é:
A verdade é que você só tem interação direta com a classe da qual herda. Pense nessa classe como uma camada - fornecendo o máximo ou o mínimo dela ou da funcionalidade de seus pais, conforme desejar para suas classes derivadas.
EDITAR:
Sua edição funciona, mas acho que usaria algo assim:
Obviamente, em uma implementação real, você pode fazer algo mais parecido com isto para extensibilidade e manutenção:
Então, as classes derivadas podem controlar o estado de seus pais adequadamente.
fonte
Derived
qual chamaBase.Say
, para que possa ser chamadaSpecialDerived
? Mais simples, não?Por que não simplesmente converter a classe filho para uma classe pai específica e invocar a implementação específica? Essa é uma situação de caso especial e uma solução de caso especial deve ser usada. Você precisará usar a
new
palavra - chave nos métodos filhos.fonte
fonte
Você também pode criar uma função simples na classe derivada de primeiro nível, para chamar a função Grand Base
fonte
Meu 2c para isso é implementar a funcionalidade que você precisa para ser chamado em uma classe de kit de ferramentas e chamar isso de onde você precisar:
Isso requer alguma reflexão sobre o acesso ao privilégio; talvez seja necessário adicionar alguns
internal
métodos de acessador para facilitar a funcionalidade.fonte
Nos casos em que você não tem acesso à fonte da classe derivada, mas precisa de toda a fonte da classe derivada, além do método atual, recomendo que você também faça uma classe derivada e chame a implementação da classe derivada.
Aqui está um exemplo:
fonte
Como pode ser visto em postagens anteriores, pode-se argumentar que, se a funcionalidade da classe precisar ser contornada, algo estará errado na arquitetura da classe. Isso pode ser verdade, mas nem sempre se pode reestruturar ou refatorar a estrutura de classes em um grande projeto maduro. Os vários níveis de gerenciamento de alterações podem ser um problema, mas manter a funcionalidade existente operando da mesma maneira após a refatoração nem sempre é uma tarefa trivial, especialmente se houver restrições de tempo. Em um projeto maduro, pode ser bastante difícil impedir que vários testes de regressão sejam aprovados após uma reestruturação do código; muitas vezes existem "esquisitices" obscuras que aparecem. Tivemos um problema semelhante em alguns casos, a funcionalidade herdada não deve ser executada (ou deve executar outra coisa). A abordagem que seguimos abaixo, foi colocar o código base que precisa ser excluído em uma função virtual separada. Essa função pode ser substituída na classe derivada e a funcionalidade excluída ou alterada. Neste exemplo, o "Texto 2" pode ser impedido de saída na classe derivada.
fonte
Parece haver muitas dessas questões envolvendo a herança de um método membro de uma classe de avós, substituindo-o em uma segunda classe e, em seguida, chamando seu método novamente de uma classe de neto. Por que não apenas herdar os membros dos avós até os netos?
Parece simples .... o neto herda o método dos avós aqui. Pense nisso ... é assim que "Object" e seus membros, como ToString (), são herdados para todas as classes em C #. Estou pensando que a Microsoft não fez um bom trabalho ao explicar a herança básica. Há muito foco no polimorfismo e na implementação. Quando vasculho a documentação deles, não há exemplos dessa idéia muito básica. :(
fonte
Se você deseja acessar os dados da classe base, deve usar a palavra-chave "this" ou usar essa palavra-chave como referência para a classe.
fonte