2012-07-06 4 views
6

este es un código pequeño que muestra los métodos virtuales.Necesita comprender el siguiente código para los métodos virtuales de C#

class A 
{ 
    public virtual void F() { Console.WriteLine("A.F"); } 
} 
class B: A 
{ 
    public override void F() { Console.WriteLine("B.F"); } 
} 
class C: B 
{ 
    new public virtual void F() { Console.WriteLine("C.F"); } 
} 
class D: C 
{ 
    public override void F() { Console.WriteLine("D.F"); } 
} 

class Test 
{ 
    static void Main() 
    { 
    D d = new D(); 
    A a = d; 
    B b = d;   

    a.F(); 
    b.F();   
} 
} 

Este código está imprimiendo el resultado a continuación:

B.F 
B.F 

No puedo entender por qué a.F() imprimirá B.F?

Pensé que imprimirá DF porque la Clase B anula la F() de Clase A, entonces este método se oculta en la Clase C usando la palabra clave "nueva", luego se anula nuevamente en la Clase D. Así que finalmente DF corsé.

pero no está haciendo eso. ¿Podría explicar por qué está imprimiendo B.F?

Respuesta

5
A a = d; 
a.F(); 

Encontrará F() de la siguiente manera.

  1. Primero en class A
  2. Luego, en class B
  3. Luego, en class C
  4. Luego, en class D

ahora F() se encontrarán en A, y B. Por lo tanto, se invocará B.F(). En class C F() es diferente (ya que es una implementación nueva y no anula desde A/B). Entonces, en el 3er paso, no se encontrará c.F(). En la Clase D, anula la nueva función creada por C, por lo que tampoco se encontrará.

Debido a la nueva palabra clave, el código resultante es como siguiente (con respecto a override virtual)

class A 
    { 
     public virtual void F() { Console.WriteLine("A.F"); } 
    } 
    class B: A 
    { 
     public override void F() { Console.WriteLine("B.F"); } 
    } 
    class C: B 
    { 
     public virtual void F1() { Console.WriteLine("C.F"); } 
    } 
    class D: C 
    { 
     public override void F1() { Console.WriteLine("D.F"); } 
    } 
+0

Gracias Tilak y todos, ahora lo tengo :-) –

2

A diferencia de la anulación de método, que permite el polimorfismo, ocultar un método con la palabra clave new es solo cuestión de nombrar (y tenga en cuenta que usar new simplemente elimina la advertencia de que está ocultando algo).

En la clase C, cuando se declara:

new public virtual void F() { ... } 

Aquí se está definiendo un nuevo método no relacionado con la superclase de F(), que pasa a tener el mismo nombre.

Cuando se asigna una instancia de F a variable de tipo A o B, llamando F() utilizando aquellos puntos variables al método definido por la superclase.

Imagine si no hubiera llamado C 's método F() pero algo diferente como G(). El siguiente código no se compilará:

a.G(); 
b.G(); 

Dado que las variables con tipos estáticos como A o B, el compilador no puede ver el método recién declarado. Es la misma situación en su ejemplo, excepto que la superclase tiene el método original llamado F() para llamar en su lugar.

1

A.F es reemplazado por B.F. Por lo tanto, cuando se invoca A.F, ejecutará B.F. B.F está 'conectado' a 'A.F'.

Ahora C.F oculta B.F con la nueva palabra clave. C.F no está conectado a B.F/A.F. Cuando crea C, y llama a F(), ejecutará C.F. Si convierte C en tipo A o B y llama a F, ejecutará B.F, ya que B.F y A.F están conectados.

C.F es anulado por D.F. Ellos están conectados. Cuando se llama C.F o D.F, ejecutará D.F. Ahora, cuando elije el objeto D a A o B, y llama a F(), llamará a B.F.

Espero que esto ayude a hacerlo más claro.

Cuestiones relacionadas