Menu
CoddyTech

Słowa kluczowe virtual i override

Część sekcji Programowanie obiektowe ścieżki C# w Coddy. Lekcja 21 z 70.

Gdy klasa pochodna dziedziczy metodę, czasami chcesz całkowicie zmienić jej działanie. Słowa kluczowe virtual i override współpracują ze sobą, aby umożliwić to w kontrolowany sposób.

Oznacz metodę jako virtual w klasie bazowej, aby zasygnalizować, że klasy pochodne mogą zastąpić jej implementację:

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

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

Słowo kluczowe override w klasie pochodnej informuje kompilator, że celowo zastępujesz metodę klasy bazowej. Bez virtual w metodzie klasy bazowej nie możesz użyć override.

Prawdziwa moc ujawnia się, gdy używasz referencji do klasy bazowej, aby przechować obiekt klasy pochodnej:

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

Mimo że myPet jest zadeklarowana jako Animal, C# wywołuje wersję Dog metody Speak(). Nazywa się to polimorfizmem w czasie wykonywania — wywoływana metoda zależy od rzeczywistego typu obiektu, a nie od zadeklarowanego typu zmiennej.

Nadal możesz uzyskać dostęp do implementacji klasy bazowej za pomocą base.Speak() wewnątrz przesłoniętej metody, jeśli chcesz rozszerzyć jej działanie, zamiast całkowicie je zastępować.

challenge icon

Wyzwanie

Łatwy

Zbudujmy system powiadomień, który pokazuje, jak klasy pochodne mogą całkowicie zastąpić zachowanie klasy bazowej za pomocą słów kluczowych virtual i override, a także demonstruje możliwości polimorfizmu w czasie wykonywania.

Utworzysz trzy pliki, aby uporządkować swój kod:

  • Notification.cs: Zdefiniuj klasę Notification w przestrzeni nazw Alerts. Ta klasa bazowa reprezentuje ogólne powiadomienie z właściwością Message (typu string) i konstruktorem, który ją ustawia. Dodaj metodę virtual o nazwie Send(), która zwraca "Sending notification: {Message}".
  • EmailNotification.cs: Zdefiniuj klasę EmailNotification w przestrzeni nazw Alerts, która dziedziczy po Notification. Dodaj właściwość Recipient (typu string) i konstruktor, który przyjmuje zarówno wiadomość, jak i odbiorcę (użyj base, aby przekazać wiadomość). Nadpisz metodę Send(), aby zwracała "Emailing {Recipient}: {Message}".
  • SmsNotification.cs: Zdefiniuj klasę SmsNotification w przestrzeni nazw Alerts, która również dziedziczy po Notification. Dodaj właściwość PhoneNumber (typu string) i konstruktor, który przyjmuje zarówno wiadomość, jak i numer telefonu. Nadpisz metodę Send(), aby zwracała "SMS to {PhoneNumber}: {Message}".
  • Program.cs: W pliku głównym utwórz instancje wszystkich trzech typów powiadomień, używając wartości wejściowych. Następnie zademonstruj polimorfizm w czasie wykonywania, przechowując wszystkie trzy w zmiennych typu Notification i wywołując dla każdej z nich Send().

Otrzymasz cztery dane wejściowe:

  • Treść powiadomienia
  • Adres e-mail odbiorcy
  • Numer telefonu do SMS-a

Wypisz wynik wywołania Send() dla każdego powiadomienia przechowywanego jako odwołanie do klasy bazowej:

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

Na przykład, jeśli danymi wejściowymi są Meeting at 3pm, alice@email.com i 555-1234, dane wyjściowe powinny wyglądać następująco:

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

Zauważ, że mimo iż wszystkie trzy obiekty są przechowywane w zmiennych typu Notification, każdy wywołuje własną nadpisaną wersję Send(). Oto polimorfizm w czasie wykonywania w praktyce!

Spróbuj swoich sił

using System;
using Alerts;

class Program
{
    public static void Main(string[] args)
    {
        // Wczytaj dane wejściowe
        string message = Console.ReadLine();
        string email = Console.ReadLine();
        string phone = Console.ReadLine();

        // TODO: Utwórz instancje wszystkich trzech typów powiadomień
        // Przechowuj je w zmiennych typu Notification, aby zademonstrować polimorfizm
        
        // TODO: Utwórz bazową instancję Notification
        Notification baseNotification;
        
        // TODO: Utwórz instancję EmailNotification (przechowywaną jako typ Notification)
        Notification emailNotification;
        
        // TODO: Utwórz instancję SmsNotification (przechowywaną jako typ Notification)
        Notification smsNotification;
        
        // TODO: Wywołaj Send() na każdej z nich i wypisz wyniki
        // Metody przesłaniające zostaną wywołane dzięki polimorfizmowi w czasie wykonania
    }
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator C# online