CodeGym /Cursos /C# SELF /Sobrescritura de métodos (Method Overriding) en C#

Sobrescritura de métodos (Method Overriding) en C#

C# SELF
Nivel 21 , Lección 2
Disponible

1. Introducción

Si ahora mismo te has puesto un poco nervioso por la palabra sobrescritura, tranqui — ¡no es nada del otro mundo, de hecho es súper útil! Sobrescribir un método es la posibilidad de cambiar el comportamiento de un método de la clase base por el tuyo propio en una clase derivada. Gracias a esto, nuestro código se vuelve flexible, ampliable y listo para la vida real, donde cada animal seguro que no quiere ser solo "algún sonido".

Para permitir sobrescribir un método, la clase base lo marca con la palabra clave virtual. La clase derivada, para cambiar la implementación, usa la palabra clave override.

Ejemplo


public class Animal
{
    public string Name { get; set; }
    public virtual void MakeSound()
    {
        Console.WriteLine("Algún sonido universal de animal...");
    }
}
        

Y ahora en la clase de perro:


public class Dog : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("¡Guau-guau!");
    }
}
        
  • En la clase base — virtual.
  • En la clase derivada — override.
  • La signatura del método (nombre, tipo de retorno, parámetros) debe coincidir.

Esquema visual

Dog hereda de Animal y puede sobrescribir MakeSound()

2. Demostración en acción

Vamos a ver cómo funciona la sobrescritura en la práctica. Creamos unos animales y probamos el sonido:

Animal pet1 = new Animal { Name = "Animal sin nombre" };
Dog pet2 = new Dog { Name = "Buddy" };

pet1.MakeSound(); // Mostrará: Algún sonido universal de animal...
pet2.MakeSound(); // Mostrará: ¡Guau-guau!

Ahora lo complicamos un poco:
¿Qué pasa si guardamos un perro en una variable de tipo Animal?

Animal pet3 = new Dog { Name = "Snoopy" };
pet3.MakeSound(); // ???

¿Qué crees que pasará?
Respuesta: Se mostrará "¡Guau-guau!"
Porque aunque la variable es de tipo Animal, en realidad "apunta" a un perro, ¡y se llamará la versión sobrescrita del método!
Aquí está la magia del enlace dinámico (o tardío).

3. Usando la palabra clave base al sobrescribir

A veces no quieres reemplazar completamente la implementación del método, sino ampliarla — por ejemplo, añadir algo tuyo y luego ejecutar el comportamiento antiguo. Para eso se usa la palabra clave base. Permite llamar a la versión del método de la clase base.


public class Cat : Animal
{
    public override void MakeSound()
    {
        base.MakeSound(); // llamada a la implementación base
        Console.WriteLine("¡Miau!");
    }
}
        

Al llamar a este método primero se escribirá "Algún sonido universal de animal...", y luego "¡Miau!"

4. Cómo se elige el método al sobrescribir

Para entender visualmente lo que pasa "bajo el capó", imagina esta tabla (despacho virtual):

Tipo de variable Tipo de objeto Qué método se llama
Animal Animal Animal.MakeSound
Animal Dog Dog.MakeSound
Animal Labrador Labrador.MakeSound
Dog Labrador Labrador.MakeSound
Dog Dog Dog.MakeSound

La regla principal:
El tipo de la variable solo importa para el compilador, pero en tiempo de ejecución se tiene en cuenta el tipo real del objeto (lo que creamos con new).
Este mecanismo se llama enlace dinámico (o tardío) — ¡es la base del polimorfismo (de eso hablaremos en la próxima lección)!

¿Para qué sobrescribir métodos?

  • En frameworks de GUI: tienes una clase base de ventana y sobrescribes métodos para dibujar elementos concretos.
  • En motores de juegos: clase base Enemy, y las clases derivadas implementan diferentes tipos de comportamiento.
  • En tests unitarios: puedes crear "stubs" (stubs, mocks) para métodos.

Los frameworks modernos de .NET usan mucho este mecanismo para eventos, código plantilla, herencia de configuraciones e incluso para serialización de objetos (por ejemplo, usando propiedades virtuales).

5. La palabra clave new al ocultar métodos

Ya hemos visto que para sobrescribir métodos hace falta el dúo virtual/override. Pero en C# hay otro modificador relacionado con métodos en la jerarquía de herencia — es new.

¿Para qué sirve new?

new se usa si en la clase derivada declaras un método con la misma signatura que en la clase base, PERO no quieres sobrescribir el método virtual, sino ocultar (enmascarar) el método base.

  • No es sobrescritura, es ocultación.
  • Ese método se llama según el tipo de la variable, no por el tipo real del objeto (¡no hay polimorfismo dinámico!).
  • El compilador te avisará si "por accidente" ocultas un método sin la palabra clave new.

Ejemplo: diferencia entre override y new


public class Animal
{
    public virtual  void MakeSound()
    {
        Console.WriteLine("El animal hace algún sonido...");
    }
}

public class Dog : Animal
{
    // Ocultamos el método de la clase base (NO sobrescribimos)
    public new void MakeSound()
    {
        Console.WriteLine("¡Esto no es override! Solo el método del perro.");
    }
}
        

Ahora veamos el comportamiento:

Animal a = new Dog();
Dog d = new Dog();

a.MakeSound(); // "El animal hace algún sonido..."
d.MakeSound(); // "¡Esto no es override! Solo el método del perro."
  • Si la variable es de tipo Dog — se llamará el método de Dog.
  • Si la variable es de tipo Animal, aunque tenga un Dog — ¡se llamará el método de Animal!

6. Feedback y particularidades de la implementación

Al principio de programar es muy común no entender por qué un método "sobrescrito" funciona como antes. Normalmente la razón es simple: en la clase base falta virtual, o en la derivada el método está declarado con new en vez de override. El segundo caso es especialmente traicionero — si llamas al método desde una variable de tipo base, se llamará la versión base, no la sobrescrita. Así que siempre revisa que usas bien las palabras clave.

Además de errores de sintaxis, a veces los que empiezan intentan cambiar el tipo de retorno al sobrescribir. Por ejemplo, hacer que la función base devuelva object y en la derivada string. Eso no se puede: la signatura del método debe coincidir completamente.

Tabla comparativa: override vs new

Característica override new
Mecanismo Sobrescribe método virtual Oculta método de la clase base
Enlace tardío Sí — funciona con polimorfismo dinámico No — funciona según el tipo de variable
Requiere que en base haya... virtual, abstract o ya override No
¿Recomendado usar? Sí, casi siempre Solo en casos excepcionales

7. Cómo funcionan los métodos sobrescritos con jerarquías

Todo este rollo de sobrescribir se pone aún más interesante si tenemos cadenas largas de herencia:


public class Animal
{
    public virtual void MakeSound()
    {
        Console.WriteLine("El animal hace algo...");
    }
}

public class Dog : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("¡Guau-guau!");
    }
}

public class Labrador : Dog
{
    public override void MakeSound()
    {
        Console.WriteLine("Soy un labrador: ¡guau-guau!");
    }
}
        

¿Qué pasa si escribimos esto?

Animal pet = new Labrador();
pet.MakeSound(); //   => "Soy un labrador: ¡guau-guau!"

C# siempre elegirá la implementación más "profunda" del método virtual que haya en el objeto real.

8. Errores típicos al sobrescribir métodos

El mundo no es perfecto, y los estudiantes (¡y los devs con experiencia también!) a veces cometen errores. Vamos a aprender a esquivar los "clásicos":

1. Olvidaste virtual en la clase base


public class Animal
{
    public void MakeSound() { ... } // Falta 'virtual'
}

public class Dog : Animal
{
    // ¡Error de compilación! No se puede sobrescribir.
    public override void MakeSound()
    {
        Console.WriteLine("¡Guau!");
    }
}
        

C# te dirá: 'Dog.MakeSound()': no suitable method found to override

2. Las signaturas no coinciden

Asegúrate de que el nombre del método, el tipo de retorno y los parámetros coinciden:


public class Animal
{
    public virtual void MakeSound() { ... }
}

public class Dog : Animal
{
    // Error: la signatura es diferente (por ejemplo, se añadió un parámetro)
    public override void MakeSound(string sound)
    {
        Console.WriteLine(sound);
    }
}
        

3. No uses new en vez de override sin motivo

La palabra clave new permite ocultar el método de la clase base, pero eso no es sobrescritura y no funciona con polimorfismo dinámico. Es otro mecanismo que normalmente deberías evitar salvo que tengas una buena razón.

2
Tarea
C# SELF, nivel 21, lección 2
Bloqueada
Uso del método base al sobrescribir
Uso del método base al sobrescribir
2
Tarea
C# SELF, nivel 21, lección 2
Bloqueada
Trabajo con la cadena de herencia
Trabajo con la cadena de herencia
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION