2010-03-23 10 views
15

Estoy aprendiendo C# y me encontré con el siguiente problema. Tengo dos clases: de base y derivados:C# Ocultación, anulación y función de llamada de la clase base

class MyBase 
{ 
    public void MyMethod() 
    { 
     Console.WriteLine("MyBase::MyMethod()"); 
    } 
} 


class MyDerived: MyBase 
{ 
    public void MyMethod() 
    { 
     Console.WriteLine("MyDerived::MyMethod()"); 
    } 
} 

Por ahora, sin virtual y override palabras clave. Cuando compilo esto, recibo la advertencia (que, por supuesto, se espera) de que trato de ocultar MyMethod de la clase MyBase.

Lo que quiero hacer es llamar al método de la clase base que tiene una instancia de clase derivada. Lo hago así:

MyDerived myDerived = new MyDerived(); 
((MyBase)myDerived).MyMethod(); 

Funciona bien cuando no se especifican virtual, etc. palabras clave en los métodos. He intentado poner combinación de las palabras clave y me dieron los siguientes resultados:

| MyBase::MyMethod | MyDerived::MyMethod | Result printed on the console | 
| -----------------|---------------------|-------------------------------| 
| -    | -     | MyBase::MyMethod()   | 
| -    | new     | MyBase::MyMethod()   | 
| virtual   | new     | MyBase::MyMethod()   | 
| virtual   | override   | MyDerived::MyMethod()   | 

espero que el cuadro es claro para usted. Tengo dos preguntas:

  1. ¿es la forma correcta de llamar a la función de la clase base (((MyBase)myDerived).MyMethod();)? Sé acerca de la palabra clave base, pero solo se puede llamar desde el interior de la clase derivada. ¿Es correcto?
  2. ¿Por qué en el último caso (con virtual y override modificadores) el método que se llamó provino de la clase derivada? ¿Podrías por favor explicar eso?
+0

¿Puede explicar lo que * quiere * y no lo que experimentó? Todo lo que puedo decir ahora es que "Sí, eso parece correcto". Para la última pregunta, debería leer sobre cómo funciona el despacho virtual de métodos. Consulte http://en.wikipedia.org/wiki/Virtual_method_table para obtener información. –

Respuesta

18

Cuando se llama a un método virtual en una instancia de un tipo que reemplaza el método, siempre se llamará la versión sustituida, igual que lances a la clase base.

La única forma de invocar la implementación base de un método virtual en una clase que anula el método es crear un segundo método en la clase derivada (no la clase base) que llama al método utilizando la palabra clave base.

En general, tener que hacer esto es un signo de un diseño API pobre: ​​si cree que deberá llamar a la versión base, la versión derivada probablemente debería tener un nombre diferente.

+2

+1 - bien explicado. Puntos extra para la discusión de diseño. –

2

Tiene la razón: base solo se puede llamar desde dentro de la clase derivada - Source.

Esta página también proporciona un ejemplo de cómo anular la definición de la clase base.

3

En cuanto a su segunda pregunta, no está cambiando el tipo de objeto al que hace referencia, solo la interfaz a la que hace referencia. Así que si usted tiene un objeto B que hereda de A y anula la función C, incluso si se refiere a B como A, que todavía llama a las implementaciones del tipo más derivado, en este caso B.

2
  1. Usted' re right, base se refiere a la clase base para una instancia determinada.
  2. El mecanismo involucrado se llama polimorfismo: debe trabajar mejor sin previo aviso. La buena forma orientada a objetos naturales es el último de los casos que mencionaste.

Por cierto, trate de evitar escribir código que haga cumplir el principio de sustitución, en otras palabras, no escriba código que dependa de la implementación de su jerarquía de clases porque tendrá que modificar este código si agregue una nueva clase derivada a su clase base.

Cuestiones relacionadas