2008-12-25 13 views

Respuesta

128

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 se llama 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 utiliza la base clasifique en todo su código en lugar de las clases heredadas, y use shadow, devolverá los valores que devuelve la clase base en lugar de seguir el árbol de herencia del tipo real del objeto.

Run code here

Esperanza estoy haciendo sentido :)

+11

Anulación proporciona polimorfismo, el sombreado proporciona una implementación diferente en ese nivel de la jerarquía, pero no polimórficamente. –

+0

@dribeas, ¿Qué definición de polimorfismo estarías usando para llegar a esa conclusión? – AnthonyWJones

+8

@AnthonyWJones, el polimorfismo es la capacidad de un tipo (derivado) para ser utilizado como un tipo diferente (base) donde la implementación real (comportamiento) es la del tipo específico real (derivado). Si anulas, el método derivado se invocará mediante referencia a la base, pero si sombreas eso no es cierto –

6

Creo que la principal diferencia es que con el sombreado, básicamente estás reutilizando el nombre, e ignorando el uso de la clase superior. Al anular, está cambiando la implementación, pero no la accesibilidad y la firma (por ejemplo, tipos de parámetros y devolución). Ver http://www.geekinterview.com/question_details/19331.

31

remedo es en realidad el lenguaje VB por lo que se refieren como escondido en C#.

A menudo la ocultación (sombreado en VB) y la anulación se muestran como en respuesta por Stormenet.

Se muestra que un método virtual está anulado por una subclase y las llamadas a ese método incluso en el tipo de superclase o desde el interior de la superclase llamarán a la implementación de reemplazo de la subclase.

Luego, se muestra un método concreto (uno que no está marcado como virtual o abstracto) que se oculta utilizando la palabra clave new 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 pierde 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. 

Nota en el ejemplo anterior DoStuff se vuelve concreto y no puede ser anulado. 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 todos los métodos involucrados siendo virtual, la anulación de C no afecta el método virtual en A, debido a la utilización de new en B oculta la Una implementación.

Editar: Se ha observado en los comentarios a esta respuesta que lo anterior puede ser peligroso o al menos no particularmente útil. Yo diría que sí, que puede ser peligroso y que estaría allí si fuera útil.

En particular, usted podría tener 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 externa de Bar, Foo 's ejecución de Cosa() sigue siendo accesible y reemplazable. Todo legal y explicable de acuerdo con las reglas de tipo .NET nunca es del todo intuitivo.

He publicado esta respuesta para profundizar en la comprensión de cómo funcionan las cosas, no como una sugerencia de técnicas que se pueden usar libremente.

+2

Es bueno saber eso. Aunque su uso puede ser peligroso :) – Stormenet

+2

Todas las herramientas pueden ser peligrosas si no se usan correctamente. – AnthonyWJones

+1

Pero, ¡la usabilidad realmente parece cuestionable! ¿Hay alguna aplicación de código abierto "seria" que use esto? – Jox

0

Básicamente, si usted tiene algo parecido a continuación,

Class A 
{ 
} 

Class B:A 
{ 
} 

A a = new B(); 

Cualquier método que se ejecuta en el objeto 'a' se realizará del 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 le dará una advertencia para usar 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 puede necesitar llamar a un método de la clase de referencia que la instancia particular contiene 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'. Por lo tanto, si desea que la llamada al método se realice en 'B', use Virtual y anule para lograr esto.

Espero que esto ayude ...

Daniel Sandeep.

3

Shadowing es un concepto de VB.NET. En C#, Shadowing se conoce como Ocultar. Oculta el método de clase derivado. 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.

Cuestiones relacionadas