Quais são as diferenças entre declarar um método em um tipo base " virtual
" e substituí-lo em um tipo filho usando a override
palavra-chave " " em vez de simplesmente usar a new
palavra-chave " " ao declarar o método correspondente no tipo filho?
c#
syntax
overriding
method-hiding
member-hiding
i3ensays
fonte
fonte
new
cria um novo membro com o mesmo nome e faz com que o membro original para ficar escondido, enquantooverride
estende a implementação de um membro herdado"Respostas:
A palavra-chave "new" não substitui, significa um novo método que não tem nada a ver com o método da classe base.
Isso imprime false, se você usasse substituir, ele seria impresso true.
(Código base retirado de Joseph Daigle)
Então, se você estiver fazendo polimorfismo real, você sempre deve substituir . O único local em que você precisa usar "novo" é quando o método não está relacionado de forma alguma à versão da classe base.
fonte
virtual
na base eoverride
derivar? Por que isso existe? O código ainda funcionará mesmo semnew
- então é puramente apenas legibilidade?Eu sempre acho coisas assim mais facilmente compreendidas com fotos:
Mais uma vez, usando o código de Joseph Daigle,
Se você chamar o código assim:
OBSERVAÇÃO: O importante é que nosso objeto seja realmente um
Bar
, mas estamos armazenando-o em uma variável do tipoFoo
(isso é semelhante a convertê-lo)Em seguida, o resultado será o seguinte, dependendo de você ter usado
virtual
/override
ounew
ao declarar suas classes.fonte
Aqui está um código para entender a diferença no comportamento de métodos virtuais e não virtuais:
fonte
new
para "ocultar" o método base, quando simplesmente não usar a substituição parece fazer o mesmo?virtual
eo compilador vai reclamar se ele vê o mesmo nome de função em uma classe "linhagem" semvirtual
assinaturao
new
palavra-chave, na verdade, cria um membro completamente novo que existe apenas nesse tipo específico.Por exemplo
O método existe nos dois tipos. Quando você usa reflexão e obtém os membros do tipo
Bar
, na verdade você encontrará 2 métodos chamadosDoSomething()
que parecem exatamente iguais. Ao usá-new
lo, você efetivamente oculta a implementação na classe base, de modo que quando as classes derivamBar
(no meu exemplo) a chamada de método parabase.DoSomething()
vaiBar
e nãoFoo
.fonte
virtual / override informa ao compilador que os dois métodos estão relacionados e que, em algumas circunstâncias, quando você pensa que está chamando o primeiro método (virtual), é realmente correto chamar o segundo método (substituído). Essa é a base do polimorfismo.
Chamará o método VirtualFoo () anulado da subclasse.
new informa ao compilador que você está adicionando um método a uma classe derivada com o mesmo nome que um método na classe base, mas eles não têm relação um com o outro.
Chamará o método NewBar () do BaseClass, enquanto que:
Irá chamar o método NewBar () da subclasse.
fonte
Além dos detalhes técnicos, acho que o uso de substituição / virtual comunica muitas informações semânticas sobre o design. Quando você declara um método virtual, indica que espera que as classes de implementação desejem fornecer suas próprias implementações não padrão. Omitir isso em uma classe base também declara a expectativa de que o método padrão seja suficiente para todas as classes de implementação. Da mesma forma, pode-se usar declarações abstratas para forçar as classes de implementação a fornecer sua própria implementação. Mais uma vez, acho que isso comunica muito sobre como o programador espera que o código seja usado. Se eu estivesse escrevendo as classes base e de implementação e me descobrisse usando novas, repensaria seriamente a decisão de não tornar o método virtual no pai e declararia minha intenção especificamente.
fonte
A diferença entre a palavra-chave de substituição e a nova palavra-chave é que a primeira substitui o método e a segunda oculta o método.
Confira os links a seguir para obter mais informações ...
MSDN e outros
fonte
new
A palavra-chave é para ocultar. - significa que você está ocultando seu método em tempo de execução. A saída será baseada no método da classe base.override
para substituir. - significa que você está chamando seu método de classe derivada com a referência da classe base. A saída será baseada no método de classe derivada.fonte
Minha versão da explicação vem do uso de propriedades para ajudar a entender as diferenças.
override
é simples o suficiente, certo? O tipo subjacente substitui o pai.new
é talvez o enganador (para mim era). Com propriedades, é mais fácil entender:Usando um depurador, você pode perceber que
Foo foo
possui 2GetSomething
propriedades, pois na verdade possui 2 versões da propriedade,Foo
eBar
' s, e saber qual usar, C # 'picaretas' a propriedade para o tipo atual.Se você quisesse usar a versão da barra, você teria usado a substituição ou a
Foo foo
substituição.Bar bar
tem apenas 1 , pois deseja um comportamento completamente novoGetSomething
.fonte
Não marcar um método com nada significa: Vincule esse método usando o tipo de compilação do objeto, não o tipo de tempo de execução (ligação estática).
Marcando um método com
virtual
meios: Vincule esse método usando o tipo de tempo de execução do objeto, não o tipo de tempo de compilação (ligação dinâmica).Marcar um
virtual
método de classe base comoverride
na classe derivada significa: Este é o método a ser vinculado usando o tipo de tempo de execução do objeto (ligação dinâmica).Marcar um
virtual
método de classe base comnew
na classe derivada significa: Este é um método novo, que não tem relação com o mesmo nome na classe base e deve ser vinculado usando o tipo de tempo de compilação do objeto (ligação estática).Não marcar um
virtual
método de classe base na classe derivada significa: Este método está marcado comonew
(ligação estática).Marcar um método
abstract
significa: Esse método é virtual, mas não declararei um corpo para ele e sua classe também é abstrata (ligação dinâmica).fonte