2010-06-01 6 views
25

estoy teniendo las siguientes clases:Confundido acerca de "anular" frente a "nuevo" en C#

class Base 
{ 
    public virtual void Print() 
    { 
     Console.WriteLine("Base"); 
    } 
} 

class Der1 : Base 
{ 
    public new virtual void Print() 
    { 
     Console.WriteLine("Der1"); 
    } 
} 

class Der2 : Der1 
{ 
    public override void Print() 
    { 
     Console.WriteLine("Der2"); 
    } 
} 

Este es mi método principal:

Base b = new Der2(); 
Der1 d1 = new Der2(); 
Der2 d2 = new Der2(); 

b.Print(); 
d1.Print(); 
d2.Print(); 

La salida es Base, Der2, Der2.

Hasta donde sé, Override no permitirá que el método anterior se ejecute, incluso si el puntero apunta a ellos. Por lo tanto, la primera línea también debería mostrar Der2. Sin embargo, salió Base.

¿Cómo es posible? ¿Cómo la anulación no funcionó allí?

+0

Realmente Un ejemplo increíble ... El único truco aquí es: - Aunque al principio, el método de la base estaba oculto por el método virtual de "Der-1", de modo de anulación método de "Der-2 "NO pudo ser implementado. Por lo tanto, obtuvimos el valor de BASE. – Kings

Respuesta

27

Nunca ha anulado la versión Base de Print(). Solo lo has ocultado con un método virtual separado (llamado igual) en Der1.

Cuando utiliza la palabra clave new en una firma de método, le está diciendo al compilador que este método tiene el mismo nombre que uno de sus clases base, pero no tiene otra relación. Puedes hacer que este nuevo método sea virtual (como lo has hecho), pero eso no es lo mismo que anular el método de la clase base.

En Der2 cuando se reemplaza Print en realidad se está anulando la 'nueva' versión que usted declaró en Der1 - no la versión es Base. Eric Lippert tiene un excellent answer a una pregunta ligeramente diferente que puede ayudarlo a razonar sobre cómo se tratan los métodos virtuales en el lenguaje C#.

En su ejemplo, cuando se llama Print, que está llamando en el primer caso a través de una referencia de tipo Base - por lo que la oculta (pero no anulado) versión de Print se llama. Las otras dos llamadas se envían a la implementación de Der1, porque en este caso, usted realmente ha anulado el método.

Puede leer más acerca de esto en el MSDN documentation of new and override.

Lo que puede haber previsto que ver con DER1 (como lo hizo con der2) es utilizar el override palabra clave:

class Base 
{ 
    public virtual void Print() 
    { 
     Console.WriteLine("Base"); 
    } 
} 

class Der1 : Base 
{ 
    // omitting 'new' and using override here will override Base 
    public override void Print() 
    { 
     Console.WriteLine("Der1"); 
    } 
} 
+0

Eso es lo que hizo con Der2. – GalacticCowboy

+0

@GalacticCowboy - de hecho, ese era mi punto. Eso es probablemente lo que se pretendía en Der1 también, pero de alguna manera se introdujo la palabra clave 'new', en lugar de 'anular'. Actualizaré mi publicación para que quede más clara. – LBushkin

+0

Gracias. Una respuesta maravillosa, comprendí completamente cómo funciona ahora. – iTayb

5

Es porque Der1 no anulaciónPrint, se sustituye por una nuevo método que tiene el mismo nombre (esto es causado por el uso de la palabra clave new). Por lo tanto, cuando el objeto se convierte a Base llama al Print en Base; no hay anulación para llamar ..

1

override reemplazará el método anterior, pero como su clase Der1 no anula Print() (que sombras que, al utilizar un VB-ismo), entonces la versión alemana de la mayoría overriden Base 's Print() se llama, que pasa a sea ​​la versión que define

0

Como todos han dicho, la clase Der1 está reemplazando Print() en lugar de anularla. Para ver esto en acción, puede basar d1 y d2 en Base y luego llamar al método de impresión. Luego devolverá Base.

((Base)d2).Print(); //Base 
Cuestiones relacionadas