Hay determinadas circunstancias
en las que cuando redefinamos un determinado método nos interese poder acceder
al código de la versión original. Por ejemplo, porque el código redefinido que
vayamos a escribir haga lo mismo que el original y además algunas cosas extras.
En estos casos se podría pensar que una forma de conseguir esto sería convirtiendo
el objeto actual al tipo del método a redefinir y entonces llamar así a ese
método, como por ejemplo en el siguiente código:
using System;
class A
{
public virtual void F()
{
Console.WriteLine(“A”);
}
}
class B:A
{
public override void F()
{
Console.WriteLine(“Antes”);
((A) this).F(); // (2)
Console.WriteLine(“Después”);
}
public static void
Main()
{
B b = new
B();
b.F();
}
}
Pues bien, si ejecutamos el
código anterior veremos que la aplicación nunca termina de ejecutarse y está
constantemente mostrando el mensaje Antes por
pantalla. Esto se debe a que debido al polimorfismo se ha entrado en un bucle
infinito: aunque usemos el operador de conversión para tratar el objeto como si
fuese de tipo A, su
verdadero tipo sigue siendo B, por
lo que la versión de F() a la que
se llamará en (2) es a
la de B de nuevo, que volverá a
llamarse así misma una y otra vez de manera indefinida.
Para solucionar esto, los
diseñadores de C# han incluido una palabra reservada llamada base que
devuelve una referencia al objeto actual semejante a this pero con la
peculiaridad de que los accesos a ella son tratados como si el verdadero tipo
fuese el de su clase base. Usando base, podríamos reemplazar el código de la redefinición
de F() de ejemplo anterior por:
public override void F()
{
Console.WriteLine(“Antes”);
base.F();
Console.WriteLine(“Después”);
}
Si ahora ejecutamos el programa
veremos que ahora sí que la versión de F() en B llama a la versión de F() en A, resultando la siguiente salida por pantalla:
Antes
A
Después
A la hora de redefinir métodos
abstractos hay que tener cuidado con una cosa: desde el método redefinidor no
es posible usar base para hacer referencia a métodos abstractos de la
clase padre, aunque sí para hacer referencia a los no abstractos. Por ejemplo:
abstract
class A
{
public abstract
void F();
public void G()
{}
}
class B: A
{
public override
void F()
{
base.G(); // Correcto
base.F(); // Error, base.F() es abstracto
}
}