Menu
CoddyTech

„virtual“- und „override“-Schlüsselwörter

Teil des Abschnitts Objektorientierte Programmierung der C#-Journey von Coddy. Lektion 21 von 70.

Wenn eine abgeleitete Klasse eine Methode erbt, möchtest du manchmal vollständig ändern, wie sich diese Methode verhält. Die Schlüsselwörter virtual und override arbeiten zusammen, um dies auf kontrollierte Weise zu ermöglichen.

Markiere eine Methode in der Basisklasse als virtual, um anzuzeigen, dass abgeleitete Klassen ihre Implementierung ersetzen dürfen:

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

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

Das Schlüsselwort override in der abgeleiteten Klasse teilt dem Compiler mit, dass du die Basismethode absichtlich überschreibst. Ohne virtual bei der Basismethode kannst du override nicht verwenden.

Die wahre Stärke zeigt sich, wenn du eine Basisklassenreferenz verwendest, um ein abgeleitetes Objekt zu halten:

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

Obwohl myPet als Animal deklariert ist, ruft C# die Dog-Version von Speak() auf. Das nennt man Laufzeit-Polymorphismus – die tatsächlich aufgerufene Methode hängt vom tatsächlichen Typ des Objekts ab, nicht vom deklarierten Typ der Variable.

Du kannst innerhalb deiner Überschreibung weiterhin mit base.Speak() auf die Basisimplementierung zugreifen, wenn du das Verhalten erweitern statt vollständig ersetzen möchtest.

challenge icon

Aufgabe

Einfach

Erstellen wir ein Benachrichtigungssystem, das zeigt, wie abgeleitete Klassen das Verhalten der Basisklasse mithilfe der Schlüsselwörter virtual und override vollständig überschreiben können, und zugleich die Leistungsfähigkeit der Laufzeit-Polymorphie veranschaulicht.

Du erstellst drei Dateien, um deinen Code zu organisieren:

  • Notification.cs: Definiere eine Notification-Klasse im Namespace Alerts. Diese Basisklasse stellt eine allgemeine Benachrichtigung mit einer Message-Eigenschaft (string) und einem Konstruktor dar, der sie festlegt. Füge eine virtual-Methode namens Send() hinzu, die "Sending notification: {Message}" zurückgibt.
  • EmailNotification.cs: Definiere eine EmailNotification-Klasse im Namespace Alerts, die von Notification erbt. Füge eine Recipient-Eigenschaft (string) und einen Konstruktor hinzu, der sowohl die Nachricht als auch den Empfänger entgegennimmt (verwende base, um die Nachricht weiterzugeben). Überschreibe die Send()-Methode so, dass sie "Emailing {Recipient}: {Message}" zurückgibt.
  • SmsNotification.cs: Definiere eine SmsNotification-Klasse im Namespace Alerts, die ebenfalls von Notification erbt. Füge eine PhoneNumber-Eigenschaft (string) und einen Konstruktor hinzu, der sowohl die Nachricht als auch die Telefonnummer entgegennimmt. Überschreibe Send() so, dass die Methode "SMS to {PhoneNumber}: {Message}" zurückgibt.
  • Program.cs: Erstelle in deiner Hauptdatei Instanzen aller drei Benachrichtigungstypen mithilfe von Eingabewerten. Zeige anschließend die Laufzeit-Polymorphie, indem du alle drei in Notification-Variablen speicherst und für jede Send() aufrufst.

Du erhältst drei Eingaben:

  • Die Benachrichtigungsnachricht
  • Die E-Mail-Adresse des Empfängers
  • Die Telefonnummer für SMS

Gib das Ergebnis des Aufrufs von Send() für jede Benachrichtigung aus, die als Referenz auf die Basisklasse gespeichert ist:

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

Wenn die Eingaben beispielsweise Meeting at 3pm, alice@email.com und 555-1234 lauten, sollte die Ausgabe so aussehen:

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

Beachte, dass jede der drei Variablen ihre eigene überschriebene Version von Send() aufruft, obwohl alle als Notification-Variablen gespeichert sind. Das ist Laufzeit-Polymorphie in Aktion!

Probier es selbst

using System;
using Alerts;

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

        // TODO: Instanzen aller drei Benachrichtigungstypen erstellen
        // Sie in Variablen vom Typ Notification speichern, um Polymorphie zu demonstrieren
        
        // TODO: Eine Basisinstanz von Notification erstellen
        Notification baseNotification;
        
        // TODO: Eine Instanz von EmailNotification erstellen (gespeichert als Typ Notification)
        Notification emailNotification;
        
        // TODO: Eine Instanz von SmsNotification erstellen (gespeichert als Typ Notification)
        Notification smsNotification;
        
        // TODO: Für jede Instanz Send() aufrufen und die Ergebnisse ausgeben
        // Aufgrund von Laufzeitpolymorphie werden die überschriebenen Methoden aufgerufen
    }
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Online-C#-Compiler