¿Cuáles son las diferencias entre declarar un método en un tipo base "virtual
" y luego anulando en un tipo de niño que usa el "override
" palabra clave en lugar de simplemente usar el "new
" palabra clave al declarar el método de coincidencia en el tipo de niño?C# - Palabra clave de uso + virtual anulación contra nuevo
Respuesta
La palabra clave "nueva" no se anula, significa un nuevo método que no tiene nada que ver con el método de la clase base.
public class Foo
{
public bool DoSomething() { return false; }
}
public class Bar : Foo
{
public new bool DoSomething() { return true; }
}
public class Test
{
public static void Main()
{
Foo test = new Bar();
Console.WriteLine (test.DoSomething());
}
}
Esto imprime falsa, si se ha utilizado anulación habría impresa cierto.
(código base tomada de Joseph Daigle)
Por lo tanto, si usted está haciendo el polimorfismo verdadero usted DEBE siempre anulan. El único lugar donde debe usar "nuevo" es cuando el método no está relacionado de ninguna manera con la versión de la clase base.
Debe revisar su código, hice los métodos estáticos (que es válido para usar la palabra clave "nueva"). Pero decidí que era más claro usar métodos de instancia. –
Gracias, me perdí la parte "estática". Debería prestar más atención al futuro – albertein
Tenga en cuenta que la línea Foo test = new Bar() es crucial aquí, la palabra clave new/override para los métodos determina a qué método se llama cuando coloca una barra en una variable Foo. –
La palabra clave new
realmente crea un miembro completamente nuevo que solo existe en ese tipo específico.
Por ejemplo
public class Foo
{
public bool DoSomething() { return false; }
}
public class Bar : Foo
{
public new bool DoSomething() { return true; }
}
el método existe en ambos tipos. Cuando utiliza el reflejo y obtiene los miembros del tipo Bar
, en realidad encontrará 2 métodos llamados DoSomething()
que se ven exactamente iguales. Al usar new
efectivamente oculta la implementación en la clase base, de modo que cuando las clases se derivan de Bar
(en mi ejemplo), la llamada al método base.DoSomething()
va a Bar
y no a Foo
.
Aquí hay algo de código para entender la diferencia en el comportamiento de los métodos virtuales y no virtuales:
class A
{
public void foo()
{
Console.WriteLine("A::foo()");
}
public virtual void bar()
{
Console.WriteLine("A::bar()");
}
}
class B : A
{
public new void foo()
{
Console.WriteLine("B::foo()");
}
public override void bar()
{
Console.WriteLine("B::bar()");
}
}
class Program
{
static int Main(string[] args)
{
B b = new B();
A a = b;
a.foo(); // Prints A::foo
b.foo(); // Prints B::foo
a.bar(); // Prints B::bar
b.bar(); // Prints B::bar
return 0;
}
}
gracias por esto, pero ¿por qué usar' new' para "ocultar" el método base, cuando simplemente no se usa la anulación parece hacer lo mismo? – mmcrae
No creo que se haya creado para evitar que se invalide la clase base. Creo que fue creado para evitar el conflicto de nombres ya que no puede anular un método que no es 'virtual' y el compilador se quejará si ve el mismo nombre de función en una clase" línea de sangre "sin la firma' virtual' – mr5
Más allá de los detalles técnicos, creo que usar virtual/override comunica mucha información semántica sobre el diseño. Cuando declara virtual un método, indica que espera que las clases implementadoras quieran proporcionar sus propias implementaciones no predeterminadas. Omitir esto en una clase base, del mismo modo, declara la expectativa de que el método predeterminado debería ser suficiente para todas las clases de implementación. Del mismo modo, uno puede usar declaraciones abstractas para obligar a las clases implementadoras a proporcionar su propia implementación. De nuevo, creo que esto comunica mucho acerca de cómo el programador espera que se use el código. Si estuviera escribiendo tanto la base como las clases de implementación y me encontrara utilizando nuevas, seriamente volvería a pensar en la decisión de no hacer el método virtual en el padre y declarar mi intención específicamente.
La técnica las explicaciones de la nueva anulación son sólidas, pero esta respuesta parece ser la más útil para guiar a los desarrolladores a usar. – Sully
virtual/override le dice al compilador que los dos métodos están relacionados y que, en algunas circunstancias en las que se podría pensar que está llamando el primer método (virtual) en realidad es correcto llamar el segundo método (anulado) en su lugar. Esta es la base del polimorfismo.
(new SubClass() as BaseClass).VirtualFoo()
Llamará al método VirtualFoo() modificado de la Subclase.
new le dice al compilador que está agregando un método a una clase derivada con el mismo nombre que un método en la clase base, pero no tienen ninguna relación entre ellos.
(new SubClass() as BaseClass).NewBar()
llamaremos método del BaseClass NewBar(), Considerando lo siguiente:
(new SubClass()).NewBar()
llamaremos método de la subclase NewBar().
me gusta mucho esta frase "dice el compilador" –
"fundación del polimorfismo" es otro refrán con clase :) –
siempre encuentro cosas como esto más fácil de entender con imágenes:
Una vez más, tomando el código de Joseph Daigle,
public class Foo
{
public /*virtual*/ bool DoSomething() { return false; }
}
public class Bar : Foo
{
public /*override or new*/ bool DoSomething() { return true; }
}
Si a continuación, llama al código como este:
Foo a = new Bar();
a.DoSomething();
NOTA: Lo importante es que nuestro objeto es en realidad un Bar
, pero estamos almacenándolo en una variable o f tipo Foo
(esto es similar a lanzarlo)
A continuación, el resultado será el siguiente, dependiendo de si usó virtual
/o override
new
al declarar sus clases.
Gracias .... pero ¿podría explicar un poco sobre la imagen anterior con respecto al casting que dijo? – odiseh
¡Vaya! Si olvidé agregar estas pocas líneas a mi anterior. comment: ¿te refieres a virtual/overriding y no vitual/new se usan solo para el concepto de polimorfismo y cuando simplemente declaras una variable (no usando casting) no significan? Gracias de nuevo. – odiseh
esta respuesta es exactamente lo que estaba buscando. El único problema que tuve es que las imágenes de flickr están bloqueadas en mi lugar de trabajo, así que tuve que acceder a ellas a través de mi teléfono ... – mezoid
new
palabra clave es para ocultar. - significa que está ocultando su método en tiempo de ejecución. La salida se basará en el método de clase base.override
para anular. - significa que está invocando su método de clase derivado con la referencia de la clase base. La salida se basará en el método de clase derivado.
Mi versión de la explicación proviene del uso de propiedades para ayudar a entender las diferencias.
override
es lo suficientemente simple, ¿no? El tipo subyacente reemplaza el principal.
new
es tal vez el engañoso (para mí lo fue). Con propiedades que es más fácil de entender:
public class Foo
{
public bool GetSomething => false;
}
public class Bar : Foo
{
public new bool GetSomething => true;
}
public static void Main(string[] args)
{
Foo foo = new Bar();
Console.WriteLine(foo.GetSomething);
Bar bar = new Bar();
Console.WriteLine(bar.GetSomething);
}
El uso de un depurador se puede observar que Foo foo
tiene GetSomething
propiedades, ya que en realidad tiene 2 versiones de la propiedad, Foo
's y Bar
' s, y conocer cuál usar, C# "elige" la propiedad para el tipo actual.
Si desea utilizar la versión de la barra, habría utilizado la anulación o el uso Foo foo
en su lugar.
Bar bar
sólo tiene , ya que quiere completamente nuevo comportamiento para GetSomething
.
- 1. C# palabra clave virtual
- 2. Anulación vs virtual
- 3. Anulación explícita de la función virtual
- 4. C# ref uso de la palabra clave
- 5. C# 'var' palabra clave contra las variables explícitamente definidas
- 6. Advertencia por falta de palabra clave virtual
- 7. Uso de la vida real de la nueva palabra clave para ocultar la implementación del método virtual? C#
- 8. instancia del uso de la palabra clave
- 9. uso de la palabra clave "using" en C#
- 10. USO palabra clave en Mysql
- 11. el uso de la palabra clave privada
- 12. ¿Qué significa la palabra clave virtual, en actionscript?
- 13. resharper "código de limpieza" contra la palabra clave 'var'
- 14. Uso de la palabra clave de bloqueo C#
- 15. el "es" palabra clave y la anulación del método Equals
- 16. Uso práctico de la palabra clave `stackalloc`
- 17. Palabra clave protegida C#
- 18. El uso de IsAssignableFrom y "es" palabra clave en C#
- 19. Ilustrando el uso de la palabra clave volátil en C#
- 20. C# utilizando la palabra clave, el uso adecuado de él
- 21. C# Patrones de uso para la palabra clave "es"
- 22. Uso práctico de la palabra clave parcial en C#
- 23. Uso de la palabra clave auto en C STL ++
- 24. ¿Cómo uso una palabra clave C# como nombre de propiedad?
- 25. Uso de la palabra clave "this" en java
- 26. Argumentos normales de Python contra argumentos de palabra clave
- 27. ¿Hay razones de peso EN CONTRA de usar la palabra clave C# "como"?
- 28. El uso de esta palabra clave Java
- 29. as3: uso de esta palabra clave
- 30. C# Uso de nuevo []
[MSDN] (http://msdn.microsoft.com/en-us/library/435f1dw2%28v=vs.80%29.aspx) dice "Usar' nuevo' crea un nuevo miembro con el mismo nombre y hace que el miembro original se oculte, mientras que 'anulación' amplía la implementación para un miembro heredado " – AminM
vea esto http://stackoverflow.com/questions/17717570/why-does-calling-a-method-in-my-derived -class-call-the-base-class-method –
MSDN - http://msdn.microsoft.com/en-us/library/ms173153.aspx – dayuloli