Preguntándose cuál es la diferencia entre lo siguiente:
Caso 1: Clase base
public void DoIt();
Caso 1: clase heredada
public new void DoIt();
Caso 2: Clase Base
public virtual void DoIt();
Caso 2: clase heredada
public override void DoIt();
Los casos 1 y 2 parecen tener el mismo efecto según las pruebas que he realizado. ¿Hay alguna diferencia o una forma preferida?
c#
inheritance
overriding
new-operator
Shiraz Bhaiji
fuente
fuente
Respuestas:
llamará
Derived.DoIt
si eso anulaBase.DoIt
.Primero llamará
Base.DoIt
, luegoDerived.DoIt
. En realidad, son dos métodos completamente separados que tienen el mismo nombre, en lugar de que el método derivado anule el método base.Fuente: blog de Microsoft
fuente
This indicates for the compiler to use the last defined implementation of a method
. ¿Cómo puede encontrar la última implementación definida de un método?override
un método cuando la clase base define el método comovirtual
. La palabravirtual
es la clase base diciendo "Hey, cuando llamo a este método, podría haber prácticamente ha sustituido por una aplicación derivada, por lo que no se sabe muy bien de antemano qué método de aplicación en realidad estoy llamando en tiempo de ejecución. Así quevirtual
significa es un marcador de posición para un método. Esto implica que los métodos que no están marcados comovirtual
no se pueden anular. Pero puede reemplazar cualquier método no virtual en una clase derivada con el modificadornew
, solo accesible a nivel derivado.virtual : indica que un heredero puede anular un método
anular : anula la funcionalidad de un método virtual en una clase base, proporcionando una funcionalidad diferente.
nuevo : oculta el método original (que no tiene que ser virtual), proporcionando una funcionalidad diferente. Esto solo debe usarse donde sea absolutamente necesario.
Cuando oculta un método, aún puede acceder al método original subiendo a la clase base. Esto es útil en algunos escenarios, pero peligroso.
fuente
override
y / onew
sinvirtual
el método padre?En el primer caso, está ocultando la definición en la clase principal. Esto significa que solo se invocará cuando se trate con el objeto como la clase secundaria. Si convierte la clase a su tipo principal, se invocará el método principal. En la segunda instancia, el método se anula y se invocará independientemente de si el objeto se convierte en la clase secundaria o primaria.
fuente
intente lo siguiente: (caso1)
Editar: virtual + anulación se resuelve en tiempo de ejecución (por lo que anular realmente anula los métodos virtuales), mientras que nuevo simplemente crea un nuevo método con el mismo nombre y oculta el antiguo, se resuelve en tiempo de compilación -> su compilador llamará al método ' ve '
fuente
En el caso 1, si usó, llame al método DoIt () de la clase heredada mientras el tipo se declara como la clase base, verá incluso la acción de la clase base.
fuente
La diferencia entre los dos casos es que en el caso 1, el
DoIt
método base no se anula, solo se oculta. Lo que esto significa es que dependiendo del tipo de la variable depende de qué método se llamará. Por ejemplo:Esto puede ser realmente confuso y resulta en un comportamiento no esperado y debe evitarse si es posible. Entonces, la forma preferida sería el caso 2.
fuente
Mi manera de tener en cuenta ambas palabras clave que son opuestas entre sí.
override
: lavirtual
palabra clave debe definirse para anular el método. El método que utiliza laoverride
palabra clave que, independientemente del tipo de referencia (referencia de la clase base o clase derivada) si se instancia con la clase base, se ejecuta el método de la clase base. De lo contrario, se ejecuta el método de clase derivada.new
: si la palabra clave es utilizada por un método, a diferencia de laoverride
palabra clave, el tipo de referencia es importante. Si se instancia con clase derivada y el tipo de referencia es clase base, se ejecuta el método de clase base. Si se instancia con clase derivada y el tipo de referencia es clase derivada, se ejecuta el método de clase derivada. Es decir, es contraste deoverride
palabra clave. En resumen, si olvida u omite agregar una nueva palabra clave al método, el compilador se comporta de manera predeterminada a medida quenew
se usa la palabra clave.Llamar en principal:
Salida:
Nuevo código de ejemplo,
Juega con el código comentando uno por uno.
fuente
Si
override
se usa la palabra clave en la clase derivada, se anula el método principal.Si
new
se utiliza la palabra clave en la clase derivada, el método derivado ocultado por el método principal.fuente
Tenía la misma pregunta y es realmente confuso, debería considerar que la anulación y las nuevas palabras clave solo funcionan con objetos de tipo de clase base y valor de clase derivada. En este caso, sólo podrás ver el efecto de anulación y nueva: Así que si usted tiene
class A
yB
,B
hereda deA
, a continuación, se instancia un objeto como éste:Ahora, al llamar a los métodos, se tendrá en cuenta su estado. Override : significa que extiende la función del método, luego usa el método en la clase derivada, mientras que new le dice al compilador que oculte el método en la clase derivada y use el método en la clase base. Aquí hay una muy buena vista de ese tema:
https://msdn.microsoft.com/EN-US/library/ms173153%28v=VS.140,d=hv.2%29.aspx?f=255&MSPPError=-2147217396
fuente
El siguiente artículo está en vb.net, pero creo que la explicación acerca de las anulaciones de nuevos vs es muy fácil de entender.
https://www.codeproject.com/articles/17477/the-dark-shadow-of-overrides
En algún momento del artículo, está esta oración:
La respuesta aceptada a esta pregunta es perfecta, pero creo que este artículo proporciona buenos ejemplos para agregar un mejor significado sobre las diferencias entre estas dos palabras clave.
fuente
De todos esos, nuevo es el más confuso. A través de la experimentación, la nueva palabra clave es como dar a los desarrolladores la opción de anular la implementación de la clase heredada con la implementación de la clase base definiendo explícitamente el tipo. Es como pensar al revés.
En el siguiente ejemplo, el resultado devolverá "Resultado derivado" hasta que el tipo se defina explícitamente como prueba BaseClass, solo entonces se devolverá "Resultado base".
fuente
La diferencia funcional no se mostrará en estas pruebas:
En este ejemplo, el Doit que se llama es el que espera que se llame.
Para ver la diferencia tienes que hacer esto:
Verá si se ejecuta la prueba de que en el caso 1 (como se la definió), el
DoIt()
enBaseClass
se llama, en el caso 2 (como se la definió), elDoIt()
enDerivedClass
se llama.fuente
En el primer caso, llamará al método DoIt () de clase derivada porque la nueva palabra clave oculta el método DoIt () de clase base.
En el segundo caso, llamará a anulación DoIt ()
dejemos crear instancia de estas clases
Todo se espera en lo anterior. Deje establecer instanciaB e instanciaC en instanciaA y llame al método DoIt () y verifique el resultado.
fuente
Todas las combinaciones de none, virtual, override, new y abstract:
fuente