Respuestas:
Bueno herencia ...
suponga que tiene estas clases:
class A {
public int Foo(){ return 5;}
public virtual int Bar(){return 5;}
}
class B : A{
public new int Foo() { return 1;} //shadow
public override int Bar() {return 1;} //override
}
entonces cuando llames a esto:
A clA = new A();
B clB = new B();
Console.WriteLine(clA.Foo()); // output 5
Console.WriteLine(clA.Bar()); // output 5
Console.WriteLine(clB.Foo()); // output 1
Console.WriteLine(clB.Bar()); // output 1
//now let's cast B to an A class
Console.WriteLine(((A)clB).Foo()); // output 5 <<<-- shadow
Console.WriteLine(((A)clB).Bar()); // output 1
Suponga que tiene una clase base y usa la clase base en todo su código en lugar de las clases heredadas, y usa shadow, devolverá los valores que devuelve la clase base en lugar de seguir el árbol de herencia del tipo real del objeto.
Espero tener sentido :)
El sombreado es en realidad el lenguaje de VB para lo que llamaríamos ocultar en C #.
A menudo, la ocultación (sombreado en VB) y la anulación se muestran como en la respuesta de Stormenet .
Se muestra que un método virtual es anulado por una subclase y las llamadas a ese método incluso en el tipo de superclase o desde el código interno de la superclase llamarán a la implementación de reemplazo desde la subclase.
Luego, se muestra un método concreto (uno no marcado como virtual o abstracto) que se oculta mediante el uso de la new
palabra clave al definir un método con una firma idéntica en la subclase. En este caso, cuando se llama al método en el tipo de superclase, se utiliza la implementación original, la nueva implementación solo está disponible en la subclase.
Sin embargo, lo que a menudo se pasa por alto es que también es posible ocultar un método virtual.
class A
{
public virtual void DoStuff() { // original implementation }
}
class B : A
{
public new void DoStuff() { //new implementation }
}
B b = new B();
A a = b;
b.DoStuff(); //calls new implementation
a.DoStuff(); //calls original implementation.
Tenga en cuenta que en el ejemplo anterior DoStuff se vuelve concreto y no se puede anular. Sin embargo, también es posible utilizar las palabras clave virtual
y new
juntas.
class A
{
public virtual void DoStuff() { // original implementation }
}
class B : A
{
public new virtual void DoStuff() { //new implementation }
}
class C : B
{
public override void DoStuff() { //replacement implementation }
}
C c = new C();
B b = c;
A a = b;
c.DoStuff(); //calls replacement implementation
b.DoStuff(); //calls replacement implementation
a.DoStuff(); //calls original implementation.
Tenga en cuenta que a pesar de que todos los métodos involucrados son virtuales, la anulación en C no afecta el método virtual en A porque el uso de new
en B oculta la implementación de A.
Editar: se señaló en los comentarios a esta respuesta que lo anterior puede ser peligroso o al menos no particularmente útil. Yo diría que sí, puede ser peligroso y estaría ahí fuera si fuera útil.
En particular, podría meterse en todo tipo de problemas si también cambia los modificadores de accesibilidad. Por ejemplo:-
public class Foo
{
internal Foo() { }
protected virtual string Thing() { return "foo"; }
}
public class Bar : Foo
{
internal new string Thing() { return "bar"; }
}
Para un heredero externo de Bar
, Foo
la implementación de Thing () sigue siendo accesible y anulable. Todo legal y explicable de acuerdo con las reglas de tipo .NET, nunca menos bastante poco intuitivo.
He publicado esta respuesta para profundizar la comprensión de cómo funcionan las cosas, no como una sugerencia de técnicas que se pueden usar libremente.
Creo que la principal diferencia es que con el sombreado, esencialmente estás reutilizando el nombre y simplemente ignorando el uso de superclase. Con la invalidación, está cambiando la implementación, pero no la accesibilidad y la firma (por ejemplo, tipos de parámetros y retorno). Consulte http://www.geekinterview.com/question_details/19331 .
El sombreado es un concepto de VB.NET. En C #, el sombreado se conoce como ocultación. Oculta el método de la clase derivada. Se logra usando la palabra clave 'nueva'.
La palabra clave Override se usa para proporcionar una implementación completamente nueva de un método de clase base (que está marcado como 'Virtual') en la clase derivada.
Básicamente, si tiene algo como a continuación,
Class A
{
}
Class B:A
{
}
A a = new B();
Cualquier método que llame al objeto 'a' se hará en el tipo de 'a' (aquí el tipo es 'A') Pero si implementa el mismo método en la clase B que ya está presente en la Clase A, el compilador darle una advertencia para que utilice una palabra clave "Nueva". Si usa "Nuevo", la advertencia desaparecerá. Aparte de esto, no hay diferencia entre usar "Nuevo" o no usarlo en la clase heredada.
En algunas situaciones, es posible que deba llamar a un método de la clase de referencia que contiene la instancia particular en ese momento en lugar de llamar a un método en el tipo de objeto. En el caso anterior, la referencia que contiene es 'B', pero el tipo es 'A'. Entonces, si desea que la llamada al método ocurra en 'B', entonces use Virtual y anule para lograr esto.
Espero que esto ayude...
Daniel Sandeep.
Si hay un caso en el que no puede alterar el contenido de una clase, digamos A
, pero desea usar algunos de sus métodos y tiene un método cuyo nombre es común, puede usar su propia implementación de método mediante la new
palabra clave.
El punto crucial es usarlo que tanto la referencia como el objeto deben ser del mismo tipo.
class A
{
public void Test()
{
Console.WriteLine("base");
}
}
class B : A
{
public new void Test()
{
Console.WriteLine("sub");
}
public static void Main(string[] args)
{
A a = new A();
B aa = new B();
a.Test();
aa.Test();
}
}