Flujo de ejecución de anulación de métodos y ocultación de métodos
Frecuentes
Visto 848 veces
4
Estoy confundido con el siguiente escenario, tenemos un conjunto de clases como este
public class A
{
public virtual string SomeMethod()
{
return "A";
}
}
public class B : A
{
public override string SomeMethod()
{
return "B";
}
}
public class C : B
{
public new virtual string SomeMethod()
{
return "C";
}
}
public class D : C
{
public override string SomeMethod()
{
return "D";
}
}
Cuando llamo al siguiente método
private void Test()
{
A a = new D();
B b = new D();
C c = new D();
D d = new D();
Console.WriteLine(a.SomeMethod()); //The method in class B is being called
Console.WriteLine(b.SomeMethod()); //The method in class B is being called
Console.WriteLine(c.SomeMethod()); //The method in class D is being called
Console.WriteLine(d.SomeMethod()); //The method in class D is being called
}
Estoy obteniendo la salida como esta
BBDD
¿Por qué se llama al método heredado, en lugar del método en el tipo declarado, y por qué el método no está en la clase? D
siendo llamado cada vez?
3 Respuestas
4
Cuando usted llama SomeMethod
en una instancia de A
(por ejemplo A foo = new <A or derived>()
), espera obtener la versión más derivada de SomeMethod
disponible. Ese es el punto de la herencia. Su código solo necesita tratar con instancias de la clase base, pero si esas instancias son realmente de una clase derivada, se invocan las implementaciones derivadas especiales. Este es el comportamiento que obtienes cuando anular un método.
Esto explica escenarios comunes como
A b = new B();
b.SomeMethod(); // B's implementation invoked
Con new
, no está anulando el método, está declarando un método completamente nuevo con el mismo nombre. Este método existe solo en la clase que lo declaró y sus hijos, no es parte de las clases base y su cadena de herencia.
Entonces que hace A a = new D(); a.SomeMethod();
¿hacer? La variable se declara como A
, por lo que cualquier método/propiedad/etc invocado en su contra debe definirse en A
. C
definió un Un nuevo Método SomeMethod
(y D
lo anula), pero este método no existe en A
, por lo que no se puede invocar aquí. La implementación más derivada de SomeMethod
(como se declara en el tipo A
) es en B
, por lo que esta es la implementación que se invoca.
Misma historia para B b = new D(); b.SomeMethod();
Es solo cuando llegamos a C c = new D(); c.SomeMethod()
que el Un nuevo El método tiene la oportunidad de ejecutarse. Esto se debe a que la variable es una C
, y así el Un nuevo Método SomeMethod
se declara por primera vez en el tipo de variable. Y como se indicó anteriormente, se invocará la versión más derivada posible, que en este caso significa la versión anulada por D
.
Y espero que todos estemos en la misma página para D d = new D(); d.SomeMethod()
:)
Otros han publicado buenos enlaces. Aquí hay otro hilo que podría ayudar: C # y ocultación de métodos
Y el último ejemplo aquí muestra un escenario aún más extraño en el que el método "nuevo" se declara como privado, por lo que otro tipo derivado en realidad hereda la versión base del método, en lugar de heredar la versión "nueva". http://msdn.microsoft.com/en-us/library/aa691135
contestado el 23 de mayo de 17 a las 11:05
"La variable se declara como A, por lo que cualquier método/propiedad/etc invocado contra ella debe definirse en A" si este es el caso, entonces ¿por qué A obj = new A(); obj.SomeMethod();
llamar al método en A
y no llamar al método en B
? - Vamsi
Gracias obj
es declarado e instanciado como A
. Solo tiene que preocuparse por estas cosas cuando tiene una variable (o un argumento de método) que se declara como clase base, pero que se instancia como una clase derivada. - Latkin
3
Intento explicarlo de otra manera.
virtual
/ override
significa que implementas / cambias el comportamiento del mismo método. es una implementacion de polimorfismo. Con new
, crea un método completamente nuevo. Sucede que tiene la misma firma que otro método, pero no tiene nada que ver con eso.
Al llamar a estos métodos, depende del tipo que tenga la referencia (tipo de tiempo de compilación), para elegir el método que realmente llame.
Tu código es equivalente a:
public class A
{
public virtual string SomeMethod()
{
return "A";
}
}
public class B : A
{
public override string SomeMethod()
{
return "B";
}
}
public class C : B
{
public virtual string AnotherMethod()
{
return "C";
}
}
public class D : C
{
public override string AnotherMethod()
{
return "D";
}
}
private void Test()
{
A a = new D();
B b = new D();
C c = new D();
D d = new D();
Console.WriteLine(a.SomeMethod()); //The method in class B is being called
Console.WriteLine(b.SomeMethod()); //The method in class B is being called
Console.WriteLine(c.AnotherMethod()); //The method in class D is being called
Console.WriteLine(d.AnotherMethod()); //The method in class D is being called
}
El compilador elige llamar a AnotherMethod para referencia de tipo C (y D).
Respondido 30 ago 12, 06:08
"¿Por qué se llama al método heredado, en lugar del método en el tipo declarado?" - Vamsi
Ese es todo el sentido de la herencia y la anulación. Se llama polimorfismo: llamas a un método, el tipo (tiempo de ejecución) en sí mismo sabe qué hacer. es.wikipedia.org/wiki/… - stefan steinegger
Mi pregunta es esta si creo una instancia como esta A obj = new A();
y llama al método obj.SomeMethod();
la salida será A
pero si inicializo la instancia de esta manera A objTest = new D();
y luego llamar al método objTest.SomeMethod();
saldrá B
, Por qué está pasando esto ? - Vamsi
Porque en tiempo de ejecución, es una implementación de D
. Por lo que ejecuta el SomeMethod
implementación encontrada en D
, que se hereda de B
. new SomeMethod
en su código que se implementa en C
y D
no se llama porque este es un método completamente diferente que solo tiene el mismo nombre. Eso es lo que trato de mostrar en mi código. - stefan steinegger
2
Ese es un comportamiento bien conocido: cuando ocultar método (con new
) se llama solo cuando accede a él a través de una instancia de tipo oculto; cuando usa la instancia de la clase base, se usa el método original.
Ocultación no es anulación.
Respondido 27 ago 12, 11:08
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas c# overloading method-hiding or haz tu propia pregunta.
Respuesta corta: debido a la
new
palabra clave - sloth@BigYellowCactus, ¿puedes elaborar? Vamsi
blogs.msdn.com/b/ericlippert/archive/2010/12/13/… - Habib