„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öchten Sie manchmal das Verhalten dieser Methode vollständig ändern. Die Schlüsselwörter virtual und override arbeiten zusammen, um dies auf kontrollierte Weise zu ermöglichen.
Markieren Sie eine Methode als virtual in der Basisklasse, um zu signalisieren, dass abgeleitete Klassen deren 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 Sie die Basis-Methode absichtlich ersetzen. Ohne virtual in der Basis-Methode können Sie override nicht verwenden.
Die wahre Stärke zeigt sich, wenn Sie eine Basisklassenreferenz verwenden, 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. Dies wird als Laufzeitpolymorphismus bezeichnet – die tatsächlich aufgerufene Methode hängt vom tatsächlichen Typ des Objekts ab, nicht vom deklarierten Typ der Variablen.
Sie können weiterhin auf die Basisimplementierung zugreifen, indem Sie base.Speak() innerhalb Ihres Overrides verwenden, wenn Sie das Verhalten erweitern möchten, anstatt es vollständig zu ersetzen.
Aufgabe
EinfachErstellen wir ein Benachrichtigungssystem, das demonstriert, wie abgeleitete Klassen das Verhalten der Basisklasse mithilfe der Schlüsselwörter virtual und override vollständig überschreiben können und gleichzeitig die Leistungsfähigkeit des Laufzeit-Polymorphismus zeigt.
Du erstellst drei Dateien, um deinen Code zu organisieren:
Notification.cs: Definiere eineNotification-Klasse imAlerts-Namespace. Diese Basisklasse stellt eine allgemeine Benachrichtigung mit einerMessage-Eigenschaft (string) und einem Konstruktor dar, der sie festlegt. Füge einevirtual-Methode namensSend()hinzu, die"Sending notification: {Message}"zurückgibt.EmailNotification.cs: Definiere eineEmailNotification-Klasse imAlerts-Namespace, die vonNotificationerbt. Füge eineRecipient-Eigenschaft (string) und einen Konstruktor hinzu, der sowohl die Nachricht als auch den Empfänger entgegennimmt (verwendebase, um die Nachricht zu übergeben). Überschreibe dieSend()-Methode, sodass sie"Emailing {Recipient}: {Message}"zurückgibt.SmsNotification.cs: Definiere eineSmsNotification-Klasse imAlerts-Namespace, die ebenfalls vonNotificationerbt. Füge einePhoneNumber-Eigenschaft (string) und einen Konstruktor hinzu, der sowohl die Nachricht als auch die Telefonnummer entgegennimmt. ÜberschreibeSend(), sodass"SMS to {PhoneNumber}: {Message}"zurückgegeben wird.Program.cs: Erstelle in deiner Hauptdatei Instanzen aller drei Benachrichtigungstypen mithilfe von Eingabewerten. Demonstriere anschließend den Laufzeit-Polymorphismus, indem du alle drei inNotification-Variablen speicherst und für jedeSend()aufrufst.
Du erhältst vier Eingaben:
- Die Benachrichtigungsnachricht
- E-Mail-Adresse des Empfängers
- Telefonnummer für SMS
Gib das Ergebnis des Aufrufs von Send() für jede Benachrichtigung aus, die als Referenzen auf die Basisklasse gespeichert sind:
{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 wie folgt aussehen:
Sending notification: Meeting at 3pm
Emailing alice@email.com: Meeting at 3pm
SMS to 555-1234: Meeting at 3pmBeachte, dass jedes Element seine eigene überschriebene Version von Notification aufruft, obwohl alle drei als Send()-Variablen gespeichert sind. Das ist Laufzeit-Polymorphismus in Aktion!
Probier es selbst
using System;
using Alerts;
class Program
{
public static void Main(string[] args)
{
// Eingaben lesen
string message = Console.ReadLine();
string email = Console.ReadLine();
string phone = Console.ReadLine();
// TODO: Instanzen aller drei Benachrichtigungstypen erstellen
// Speichere sie in Notification Variablen, um Polymorphie zu demonstrieren
// TODO: Eine Basis-Notification erstellen
Notification baseNotification;
// TODO: Eine EmailNotification erstellen (gespeichert als Notification Typ)
Notification emailNotification;
// TODO: Eine SmsNotification erstellen (gespeichert als Notification Typ)
Notification smsNotification;
// TODO: Send() für jede aufrufen und die Ergebnisse ausgeben
// Die überschriebenen Methoden werden aufgrund von Laufzeitpolymorphie aufgerufen
}
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienNamespaces & DirektivenEinführung in Klassen & ObjekteDas 'this'-SchlüsselwortMethoden und ParameterFelder vs. EigenschaftenKonstruktorenObjektinitialisiererWiederholung – Einfacher Taschenrechner4Vererbung
Grundlegende Vererbungs-(:)-SyntaxDas „base“-Schlüsselwort„virtual“- und „override“-SchlüsselwörterVersiegelte KlassenDie „object“-BasisklasseWiederholung – Mitarbeiterhierarchie7Erweiterte Funktionen
Überladen von OperatorenIndexer (this[])ToString()-ÜberschreibungErweiterungsmethodenRückblick – Benutzerdefinierte Liste10Entwurfsmuster Teil 1
Einführung in EntwurfsmusterThread-sicheres SingletonFactory-MusterObserver-Muster (Events)Strategy-Muster13Abschließende Herausforderungen
E-Learning-PlattformKomponente für SpielfigurenFahrzeugvermietungsdienst2Eigenschaften & statische Member
Automatisch implementierte EigenschaftenNur lesbare/schreibbare EigenschaftenStatische Felder & MethodenStatische KlassenMember mit Ausdruckskörpern5Polymorphie & Interfaces
Compile- vs. Laufzeit-PolymorphieInterface vs. abstrakte KlasseMehrere InterfacesExplizite InterfacesUpcasting & DowncastingWiederholung – Formenrechner3Klassenarchitektur
Instanz- vs. statische DatenSchlüsselwörter 'readonly' & 'const'Backing FieldsRückblick – Bankkontenverwaltung6Kapselung
ZugriffsmodifikatorenEigenschaften zur KapselungImplementierung der DatenkapselungMuster für UnveränderlichkeitRückblick – SchülerdatenÜbe selbstständig: Online-C#-Compiler