Existe alguma maneira de substituir um método não virtual? ou algo que dá resultados semelhantes (diferente de criar um novo método para chamar o método desejado)?
Eu gostaria de substituir um método Microsoft.Xna.Framework.Graphics.GraphicsDevice
com o teste de unidade em mente.
c#
overriding
overloading
zfedoran
fonte
fonte
Respostas:
Não, você não pode substituir um método não virtual. A coisa mais próxima que você pode fazer é ocultar o método criando um
new
método com o mesmo nome, mas isso não é aconselhável, pois quebra os bons princípios de design.Mas mesmo ocultar um método não dará a você o tempo de execução do despacho polimórfico de chamadas de método como uma verdadeira chamada de método virtual faria. Considere este exemplo:
Neste exemplo, ambas as chamadas para o
M
método printFoo.M
. Como você pode ver esta abordagem permitirá que você tenha uma nova implementação de um método, desde que a referência a esse objeto é do tipo derivado correto, mas escondendo um método base faz polimorfismo pausa.Eu recomendo que você não oculte métodos básicos dessa maneira.
Eu tendo a ficar do lado daqueles que favorecem o comportamento padrão do C #, que os métodos são não virtuais por padrão (ao contrário do Java). Eu iria ainda mais longe e diria que as classes também deveriam ser fechadas por padrão. A herança é difícil de projetar adequadamente e o fato de haver um método que não está marcado como virtual indica que o autor desse método nunca pretendeu que o método fosse sobrescrito.
Editar: "envio polimórfico do tempo de execução" :
O que quero dizer com isso é o comportamento padrão que ocorre em tempo de execução quando você chama métodos virtuais. Digamos, por exemplo, que em meu exemplo de código anterior, em vez de definir um método não virtual, eu de fato defini um método virtual e um verdadeiro método substituído.
Se eu fosse chamar
b.Foo
nesse caso, o CLR determinaria corretamente o tipo de objeto para o qual ab
referência apontaBar
e despacharia a chamadaM
apropriadamente.fonte
Não, você não pode.
Você só pode substituir um método virtual - consulte o MSDN aqui :
fonte
Se a classe base não for selada, você pode herdar dela e escrever um novo método que oculte o básico (use a palavra-chave "new" na declaração do método). Caso contrário, não, você não pode substituí-lo porque nunca foi a intenção do autor original que fosse substituído, daí porque não é virtual.
fonte
Acho que você está ficando sobrecarregado e confuso de sobreposição, sobrecarregar significa que você tem dois ou mais métodos com o mesmo nome, mas diferentes conjuntos de parâmetros, enquanto sobrepor significa que você tem uma implementação diferente para um método em uma classe derivada (substituindo ou modificando assim o comportamento em sua classe base).
Se um método for virtual, você pode substituí-lo usando a palavra-chave override na classe derrived. No entanto, os métodos não virtuais só podem ocultar a implementação básica usando a nova palavra-chave no lugar da palavra-chave override. A rota não virtual é inútil se o chamador acessa o método por meio de uma variável digitada como o tipo base, pois o compilador usaria um despacho estático para o método base (significando que o código em sua classe derivada nunca seria chamado).
Nunca há nada que o impeça de adicionar uma sobrecarga a uma classe existente, mas apenas o código que sabe sobre sua classe seria capaz de acessá-la.
fonte
Você não pode substituir o método não virtual de qualquer classe em C # (sem hackear o CLR), mas pode substituir qualquer método de interface que a classe implemente. Considere que temos não selados
E aqui está a demonstração
fonte
No caso de você estar herdando de uma classe não derivada, pode simplesmente criar uma superclasse abstrata e herdar dela posteriormente.
fonte
Você não pode substituir um método não virtual. No entanto, você pode usar a
new
palavra-chave modificadora para obter resultados semelhantes:Você também desejará certificar-se de que o modificador de acesso também é o mesmo, caso contrário, você não obterá herança no futuro. Se outra classe herdar da palavra
Class1
-new
chave inClass1
, não afetará os objetos que herdam dela, a menos que o modificador de acesso seja o mesmo.Se o modificador de acesso não for o mesmo:
... versus se o modificador de acesso for o mesmo:
Conforme apontado em uma resposta anterior, este não é um bom princípio de design.
fonte
Existe uma maneira de fazer isso usando classe abstrata e método abstrato.
Considerar
Agora, se você deseja ter diferentes versões do método MethodToBeTested (), altere a base de classe para uma classe abstrata e o método MethodToBeTested () como um método abstrato
Com o void abstrato MethodToBeTested () surge um problema; a implementação acabou.
Portanto, crie um
class DefaultBaseImplementation : Base
para ter a implementação padrão.E crie outro
class UnitTestImplementation : Base
para ter implementação de teste de unidade.Com essas 2 novas classes, a funcionalidade da classe base pode ser substituída.
Agora você tem 2 classes implementando (substituindo)
MethodToBeTested()
.Você pode instanciar a classe (derivada) conforme necessário (ou seja, com implementação básica ou com implementação de teste de unidade).
fonte