Menu
Coddy logo textTech

Parole chiave virtual e override

Fa parte della sezione Programmazione orientata agli oggetti del percorso C# di Coddy. Lezione 21 di 70.

Quando una classe derivata eredita un metodo, a volte vuoi cambiare completamente il comportamento di quel metodo. Le parole chiave virtual e override collaborano per renderlo possibile in modo controllato.

Contrassegna un metodo come virtual nella classe base per indicare che le classi derivate possono sostituirne l’implementazione:

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

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

La parola chiave override nella classe derivata indica al compilatore che stai sostituendo intenzionalmente il metodo della classe base. Senza virtual sul metodo della classe base, non puoi usare override.

La vera potenza si vede quando usi un riferimento alla classe base per contenere un oggetto derivato:

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

Anche se myPet è dichiarato come Animal, C# chiama la versione di Dog di Speak(). Questo si chiama polimorfismo in fase di esecuzione: il metodo effettivamente chiamato dipende dal tipo reale dell'oggetto, non dal tipo dichiarato della variabile.

Puoi comunque accedere all’implementazione di base usando base.Speak() all’interno del tuo override se vuoi estendere il comportamento anziché sostituirlo completamente.

challenge icon

Sfida

Facile

Costruiamo un sistema di notifiche che dimostri come le classi derivate possano eseguire l'override completo del comportamento della classe base usando le parole chiave virtual e override, mostrando al contempo la potenza del polimorfismo in fase di esecuzione.

Creerai tre file per organizzare il codice:

  • Notification.cs: definisci una classe Notification nello spazio dei nomi Alerts. Questa classe base rappresenta una notifica generica con una proprietà Message (string) e un costruttore che la imposta. Includi un metodo virtual chiamato Send() che restituisce "Sending notification: {Message}".
  • EmailNotification.cs: definisci una classe EmailNotification nello spazio dei nomi Alerts che eredita da Notification. Aggiungi una proprietà Recipient (string) e un costruttore che accetta sia il messaggio sia il destinatario (usa base per passare il messaggio). Esegui l'override del metodo Send() affinché restituisca "Emailing {Recipient}: {Message}".
  • SmsNotification.cs: definisci una classe SmsNotification nello spazio dei nomi Alerts che eredita anch'essa da Notification. Aggiungi una proprietà PhoneNumber (string) e un costruttore che accetta sia il messaggio sia il numero di telefono. Esegui l'override di Send() affinché restituisca "SMS to {PhoneNumber}: {Message}".
  • Program.cs: nel file principale, crea istanze di tutti e tre i tipi di notifica usando i valori di input. Poi dimostra il polimorfismo in fase di esecuzione memorizzando tutte e tre in variabili di tipo Notification e chiamando Send() su ciascuna.

Riceverai quattro input:

  • Il messaggio di notifica
  • L'indirizzo email del destinatario
  • Il numero di telefono per gli SMS

Stampa il risultato della chiamata a Send() su ciascuna notifica, memorizzata come riferimento alla classe base:

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

Ad esempio, se gli input sono Meeting at 3pm, alice@email.com e 555-1234, l'output dovrebbe essere:

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

Nota che, anche se tutte e tre sono memorizzate in variabili di tipo Notification, ognuna chiama la propria versione di Send() sottoposta a override. Questo è il polimorfismo in fase di esecuzione!

Provalo tu

using System;
using Alerts;

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

        // TODO: Crea istanze di tutti e tre i tipi di notifica
        // Memorizzale in variabili di tipo Notification per dimostrare il polimorfismo
        
        // TODO: Crea un'istanza della classe base Notification
        Notification baseNotification;
        
        // TODO: Crea un'istanza di EmailNotification (memorizzata come tipo Notification)
        Notification emailNotification;
        
        // TODO: Crea un'istanza di SmsNotification (memorizzata come tipo Notification)
        Notification smsNotification;
        
        // TODO: Chiama Send() su ciascuna istanza e stampa i risultati
        // I metodi ridefiniti verranno chiamati grazie al polimorfismo a runtime
    }
}
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore C# online