Menu
Coddy logo textTech

Palabras clave Virtual y Override

Parte de la sección Programación Orientada a Objetos del Journey de C# de Coddy — lección 21 de 70.

Cuando una clase derivada hereda un método, a veces se desea cambiar completamente el comportamiento de ese método. Las palabras clave virtual y override trabajan juntas para hacer esto posible de una manera controlada.

Marca un método como virtual en la clase base para indicar que las clases derivadas tienen permitido reemplazar su implementación:

public class Animal
{
    public virtual void Speak()
    {
        Console.WriteLine("Some sound");
    }
}

public class Dog : Animal
{
    public override void Speak()
    {
        Console.WriteLine("Woof!");
    }
}

La palabra clave override en la clase derivada le indica al compilador que estás reemplazando intencionadamente el método base. Sin virtual en el método base, no puedes usar override.

El verdadero poder se muestra cuando usas una referencia de clase base para contener un objeto derivado:

Animal myPet = new Dog();
myPet.Speak();  // Salida: Woof!

Aunque myPet está declarado como Animal, C# llama a la versión Dog de Speak(). Esto se llama polimorfismo en tiempo de ejecución - el método real que se llama depende del tipo verdadero del objeto, no del tipo declarado de la variable.

Aún puedes acceder a la implementación base usando base.Speak() dentro de tu anulación si deseas extender en lugar de reemplazar completamente el comportamiento.

challenge icon

Desafío

Fácil

Vamos a construir un sistema de notificaciones que demuestre cómo las clases derivadas pueden sobrescribir completamente el comportamiento de la clase base utilizando las palabras clave virtual y override, al tiempo que mostramos el poder del polimorfismo en tiempo de ejecución.

Crearás tres archivos para organizar tu código:

  • Notification.cs: Define una clase Notification en el espacio de nombres Alerts. Esta clase base representa una notificación genérica con una propiedad Message (string) y un constructor que la establece. Incluye un método virtual llamado Send() que devuelva "Sending notification: {Message}".
  • EmailNotification.cs: Define una clase EmailNotification en el espacio de nombres Alerts que herede de Notification. Añade una propiedad Recipient (string) y un constructor que acepte tanto el mensaje como el destinatario (usa base para pasar el mensaje). Sobrescribe el método Send() para que devuelva "Emailing {Recipient}: {Message}".
  • SmsNotification.cs: Define una clase SmsNotification en el espacio de nombres Alerts que también herede de Notification. Añade una propiedad PhoneNumber (string) y un constructor que acepte tanto el mensaje como el número de teléfono. Sobrescribe Send() para que devuelva "SMS to {PhoneNumber}: {Message}".
  • Program.cs: En tu archivo principal, crea instancias de los tres tipos de notificación utilizando los valores de entrada. Luego, demuestra el polimorfismo en tiempo de ejecución almacenando los tres en variables de tipo Notification y llamando a Send() en cada una.

Recibirás cuatro entradas:

  • El mensaje de la notificación
  • La dirección de correo electrónico del destinatario
  • El número de teléfono para el SMS

Imprime el resultado de llamar a Send() en cada notificación, almacenadas como referencias de la clase base:

{base notification Send() result}
{email notification Send() result}
{sms notification Send() result}

Por ejemplo, si las entradas son Meeting at 3pm, alice@email.com, y 555-1234, la salida debería ser:

Sending notification: Meeting at 3pm
Emailing alice@email.com: Meeting at 3pm
SMS to 555-1234: Meeting at 3pm

Observa cómo, aunque las tres están almacenadas como variables de tipo Notification, cada una llama a su propia versión sobrescrita de Send(). ¡Eso es el polimorfismo en tiempo de ejecución en acción!

Hoja de referencia

Utilice la palabra clave virtual en una clase base para marcar un método que las clases derivadas pueden sobrescribir:

public class Animal
{
    public virtual void Speak()
    {
        Console.WriteLine("Some sound");
    }
}

Utilice la palabra clave override en una clase derivada para reemplazar la implementación del método de la clase base:

public class Dog : Animal
{
    public override void Speak()
    {
        Console.WriteLine("Woof!");
    }
}

El polimorfismo en tiempo de ejecución ocurre cuando una referencia de clase base contiene un objeto derivado; el método real llamado depende del tipo real del objeto, no del tipo declarado de la variable:

Animal myPet = new Dog();
myPet.Speak();  // Salida: Woof!

Puede acceder a la implementación base dentro de una sobrescritura utilizando base:

public override void Speak()
{
    base.Speak();  // Llama a la versión de la clase base
    Console.WriteLine("Woof!");
}

Pruébalo tú mismo

using System;
using Alerts;

class Program
{
    public static void Main(string[] args)
    {
        // Leer entradas
        string message = Console.ReadLine();
        string email = Console.ReadLine();
        string phone = Console.ReadLine();

        // TODO: Crear instancias de los tres tipos de notificación
        // Almacenarlas en variables Notification para demostrar el polimorfismo
        
        // TODO: Crear una Notification base
        Notification baseNotification;
        
        // TODO: Crear una EmailNotification (almacenada como tipo Notification)
        Notification emailNotification;
        
        // TODO: Crear una SmsNotification (almacenada como tipo Notification)
        Notification smsNotification;
        
        // TODO: Llamar a Send() en cada una e imprimir los resultados
        // Se llamará a los métodos sobrescritos debido al polimorfismo en tiempo de ejecución
    }
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos