Pensando em qual é a diferença entre o seguinte:
Caso 1: Classe Base
public void DoIt();
Caso 1: Classe herdada
public new void DoIt();
Caso 2: Classe Base
public virtual void DoIt();
Caso 2: Classe herdada
public override void DoIt();
Os casos 1 e 2 parecem ter o mesmo efeito com base nos testes que eu executei. Existe uma diferença ou uma maneira preferida?
c#
inheritance
overriding
new-operator
Shiraz Bhaiji
fonte
fonte
Respostas:
chamará
Derived.DoIt
se isso substituirBase.DoIt
.Ligará primeiro
Base.DoIt
, entãoDerived.DoIt
. Eles são efetivamente dois métodos completamente separados que têm o mesmo nome, em vez do método derivado substituindo o método base.Fonte: Microsoft blog
fonte
This indicates for the compiler to use the last defined implementation of a method
. como encontrar a última implementação definida de um método?override
um método quando a classe base define o método comovirtual
. A palavravirtual
é a classe base dizendo "Hey, quando eu chamar esse método, que poderia ter praticamente foi substituído por uma aplicação derivada, então eu realmente não sei de antemão o que implementação do método Na verdade, estou chamando em tempo de execução. Assimvirtual
significa é . um espaço reservado para um método Isto implica que os métodos que não são marcados comovirtual
não pode ser substituído Mas você pode. substituir qualquer método não-virtual em uma classe derivada com o modificadornew
, acessíveis apenas a nível derivada.virtual : indica que um método pode ser substituído por um herdeiro
substituir : substitui a funcionalidade de um método virtual em uma classe base, fornecendo funcionalidade diferente.
novo : oculta o método original (que não precisa ser virtual), fornecendo funcionalidades diferentes. Isso só deve ser usado onde for absolutamente necessário.
Quando você oculta um método, você ainda pode acessar o método original fazendo a conversão para a classe base. Isso é útil em alguns cenários, mas perigoso.
fonte
override
e / ounew
nãovirtual
no método pai?No primeiro caso, você está ocultando a definição na classe pai. Isso significa que ele será invocado apenas quando você estiver lidando com o objeto como a classe filho. Se você converter a classe para seu tipo pai, o método do pai será chamado. Na segunda instância, o método é substituído e será chamado, independentemente de o objeto ser convertido como filho ou classe pai.
fonte
tente o seguinte: (case1)
Edit: virtual + override são resolvidos em tempo de execução (então a substituição realmente substitui os métodos virtuais), enquanto os novos apenas criam um novo método com o mesmo nome e ocultam o antigo, ele é resolvido em tempo de compilação -> seu compilador chamará o método de ' vê '
fonte
No caso 1, se você usou o método DoIt () da classe herdada enquanto o tipo é declarado como a classe base, você verá a ação da classe base mesmo.
fonte
A diferença entre os dois casos é que, no caso 1, o
DoIt
método base não é substituído, apenas oculto. O que isso significa é que, dependendo do tipo da variável, depende de qual método será chamado. Por exemplo:Isso pode ser realmente confuso e resultar em comportamento não esperado e deve ser evitado, se possível. Portanto, a maneira preferida seria o caso 2.
fonte
Minha maneira de ter em mente as duas palavras-chave é que elas são opostas uma à outra.
override
:virtual
palavra - chave deve ser definida para substituir o método. O método que utiliza aoverride
palavra-chave que, independentemente do tipo de referência (referência da classe base ou classe derivada), se for instanciado com a classe base, o método da classe base será executado. Caso contrário, o método da classe derivada será executado.new
: se a palavra-chave for usada por um método, ao contrário daoverride
palavra-chave, o tipo de referência é importante. Se for instanciado com a classe derivada e o tipo de referência for a classe base, o método da classe base será executado. Se for instanciado com a classe derivada e o tipo de referência for a classe derivada, o método da classe derivada será executado. Ou seja, é contraste deoverride
palavra-chave. Por outro lado, se você esquecer ou omitir adicionar nova palavra-chave ao método, o compilador se comporta por padrão à medida que anew
palavra-chave é usada.Ligue para o principal:
Resultado:
Novo exemplo de código,
Brinque com o código comentando um por um.
fonte
Se a palavra
override
- chave for usada na classe derivada, ela substituirá o método pai.Se a palavra
new
- chave for usada na classe derive, derive o método oculto pelo método pai.fonte
Eu tinha a mesma pergunta e é realmente confusa, você deve considerar que a substituição e as novas palavras-chave funcionem apenas com objetos do tipo classe base e valor da classe derivada. Nesse caso, apenas você verá o efeito de substituir e novo: portanto, se você possui
class A
eB
,B
herda deA
, instancia um objeto como este:Agora, ao chamar métodos, o estado será levado em consideração. Substituir : significa que ele estende a função do método e, em seguida, usa o método na classe derivada, enquanto novos dizem ao compilador para ocultar o método na classe derivada e, em vez disso, usar o método na classe base. Aqui está uma visão muito boa desse assunto:
https://msdn.microsoft.com/EN-US/library/ms173153%28v=VS.140,d=hv.2%29.aspx?f=255&MSPPError=-2147217396
fonte
O artigo abaixo está no vb.net, mas acho que a explicação sobre novas substituições vs é muito fácil de entender.
https://www.codeproject.com/articles/17477/the-dark-shadow-of-overrides
Em algum momento do artigo, existe esta frase:
A resposta aceita para esta pergunta é perfeita, mas acho que este artigo fornece bons exemplos para adicionar um significado melhor às diferenças entre essas duas palavras-chave.
fonte
Fora de tudo isso, o novo é o mais confuso. Através da experimentação, a nova palavra-chave é como dar aos desenvolvedores a opção de substituir a implementação da classe herdada pela implementação da classe base, definindo explicitamente o tipo. É como pensar o contrário.
No exemplo abaixo, o resultado retornará "Resultado derivado" até que o tipo seja explicitamente definido como teste BaseClass, somente então "Resultado base" será retornado.
fonte
A diferença funcional não será mostrada nestes testes:
Neste exemplo, o Doit que é chamado é o que você espera que seja chamado.
Para ver a diferença, você precisa fazer o seguinte:
Você verá se executar esse teste que, no caso 1 (como você o definiu), o
DoIt()
inBaseClass
é chamado, no caso 2 (como você o definiu), oDoIt()
inDerivedClass
é chamado.fonte
No primeiro caso, ele chamará o método DoIt () da classe derivada porque a nova palavra-chave oculta o método DoIt () da classe base.
No segundo caso, ele chamará DoIt () substituído
vamos criar instância dessas classes
Tudo é esperado acima. Deixe definir instanceB e instanceC como instanceA e chame o método DoIt () e verifique o resultado.
fonte
Todas as combinações de nenhuma, virtual, substituição, nova e abstrata:
fonte