INF.04 · C# · lekcja 14
Polimorfizm i metody wirtualne
Ten sam kontrakt, inne wykonanie
- Zrozum
- Sprawdź
- Napisz sam
Po tej lekcji: ten sam kontrakt, inne wykonanie
Dzisiaj zrobisz konkretną rzecz
Polimorfizm to trzecia z czterech głównych zasad OOP (po hermetyzacji i dziedziczeniu) i jeden z tematów, w których uczniowie najczęściej czują się niepewnie na egzaminie — a jednocześnie jedna z najbardziej praktycznych technik, eliminująca długie łańcuchy warunków sprawdzających typ obiektu.
Naciśnięcie "drukuj" działa tak samo niezależnie od tego, jaka konkretnie drukarka jest podłączona (laserowa, atramentowa, etykiet) — każda "wie", jak zinterpretować to samo polecenie na swój własny sposób. To właśnie polimorfizm.
Sprawdź w działaniu
Ten sam kontrakt, inne wykonanie
Najpierw przewidź wynik. Zmień dane w modelu i porównaj efekt. Spróbuj także przypadku granicznego, a nie tylko pierwszego poprawnego przykładu.
Model pokazuje wybraną zasadę. Nie uruchamia ani nie ocenia wklejonego kodu C#.
1. Przygotuj i uruchom własny projekt
2. Najpierw mały przykład
Wykonaj tę próbę przed dłuższym rozwiązaniem. virtual pozwala nadpisać metodę, override robi to w klasie pochodnej. Zmienna ma typ Pracownik, lecz rzeczywisty obiekt jest Programista — to jego implementacja zostanie wykonana.
Pracownik osoba = new Programista();
Console.WriteLine(osoba.Opis());
class Pracownik { public virtual string Opis() => "Pracownik"; }
class Programista : Pracownik
{
public override string Opis() => "Programista";
}
Programista
- Co sprawdzić? Zmień jedną wartość i przed uruchomieniem zapisz przewidywany rezultat. Porównaj go z opisem wyniku; przy błędzie wróć do konkretnej instrukcji.
Jak to działa — 1
Polimorfizm (z greckiego "wiele form") pozwala, żeby TO SAMO wywołanie metody zachowywało się RÓŻNIE, w zależności od tego, na jakim konkretnie obiekcie zostało wywołane — nawet jeśli w kodzie operujesz na nich przez wspólny typ bazowy.
Aby to działało, klasa bazowa musi oznaczyć metodę jako virtual ("może zostać nadpisana"), a klasa pochodna nadpisuje ją słowem override:
class Pracownik { public virtual double ObliczPremie() { return Pensja * 0.05; } }
class Kierownik : Pracownik { public override double ObliczPremie() { return Pensja * 0.20; } }
Dzięki temu możesz mieć tablicę czy listę typu bazowego (Pracownik[]), przechowującą obiekty RÓŻNYCH klas pochodnych, i wywołać na każdym tę samą metodę — C# sam "wie", którą wersję uruchomić, sprawdzając RZECZYWISTY typ obiektu, nie typ zmiennej.
Bez polimorfizmu musiałbyś sprawdzać typ każdego obiektu ręcznie (if (p is Kierownik) { ... } else if (p is Programista) { ... }) — z polimorfizmem ten cały łańcuch warunków znika, bo każdy obiekt "sam wie", jak się zachować.
Jak to działa — 2
To jedna z najważniejszych korzyści programowania obiektowego: możesz dodać NOWĄ klasę pochodną (np. Stazysta) w przyszłości, bez zmiany ani jednej linii kodu, który już korzysta z polimorficznego wywołania ObliczPremie().
3. Pełny przykład — czytaj od Main
Teraz zastąp Program.cs tym programem. Zanim uruchomisz, znajdź dane wejściowe, operację i miejsce prezentacji wyniku. W tym wariancie zachowujemy jawny Main. Nie wklejaj kilku pełnych programów do jednego pliku.
using System;
class Pracownik
{
public string Imie;
public double Pensja;
public Pracownik(string imie, double pensja)
{
Imie = imie;
Pensja = pensja;
}
public virtual double ObliczPremie() // "virtual" = może być nadpisana
{
return Pensja * 0.05;
}
}
class Kierownik : Pracownik
{
public Kierownik(string imie, double pensja) : base(imie, pensja) { }
public override double ObliczPremie() // "override" = własna wersja
{
return Pensja * 0.20;
}
}
class Stazysta : Pracownik
{
public Stazysta(string imie, double pensja) : base(imie, pensja) { }
public override double ObliczPremie()
{
return 0; // stażyści na razie bez premii
}
}
class Program
{
static void Main()
{
Pracownik[] zespol = {
new Pracownik("Ala", 5000),
new Kierownik("Bartek", 9000),
new Stazysta("Celina", 3000)
};
foreach (Pracownik p in zespol)
{
// to samo wywołanie - RÓŻNY wynik dla każdego typu!
Console.WriteLine(p.Imie + ": premia = " + p.ObliczPremie() + " zł");
}
}
}
- Prześledź kod Tablica
Pracownik[] zespolprzechowuje TRZY RÓŻNE typy obiektów (Pracownik,Kierownik,Stazysta) — to możliwe właśnie dzięki dziedziczeniu (Lekcja 13), bo każdy z nich JEST RODZAJEMPracownik. Pętlaforeachwywołujep.ObliczPremie()identycznie dla każdego elementu, ale C# w czasie DZIAŁANIA programu sprawdza rzeczywisty typ obiektu i uruchamia WŁAŚCIWĄ, nadpisaną wersję metody — to się nazywa wiązanie dynamiczne.
Sprawdź, zanim przepiszesz cały program
Najczęstszy błąd to zapomnienie słowa virtual w metodzie klasy bazowej — bez niego override w klasie pochodnej zgłosi błąd kompilacji, bo metoda nie jest oznaczona jako "nadpisywalna". Drugi błąd: użycie new zamiast override przy nadpisywaniu metody — to UKRYWA metodę bazową zamiast ją nadpisać, co psuje polimorfizm (przy wywołaniu przez typ bazowy uruchomi się stara wersja). Trzeci: ręczne sprawdzanie typu obiektu (if (p is Kierownik)) tam, gdzie polimorfizm załatwiłby sprawę prościej i bezpieczniej.
Ćwiczenie z pomocą · samodzielna praca
4. Teraz Twoja zmiana
Dodaj do przykładu z lekcji nową klasę pochodną Dyrektor : Pracownik z premią 30%, bez zmiany kodu w Main() poza dodaniem nowego obiektu do tablicy.
Spełnij warunki polecenia. Zapisz wejście, otrzymany wynik i wyjaśnij, która część kodu za niego odpowiada.
? Potrzebujesz pomocy? Rozwiązuj krok po kroku.
Krok 1 — pokaż podpowiedź
Wróć do podstawowej formy oraz objaśnienia: virtual pozwala nadpisać metodę, override robi to w klasie pochodnej. Zmienna ma typ Pracownik, lecz rzeczywisty obiekt jest Programista — to jego implementacja zostanie wykonana.
Krok 2 — pokaż podpowiedź
Zmień tylko część potrzebną do polecenia. Zachowaj działającą wersję przed zmianą i uruchamiaj po każdym małym etapie.
Krok 3 — pokaż podpowiedź
Sprawdź przypadek zwykły i graniczny; porównaj z regułą: Programista
Otwórz tylko tyle podpowiedzi, ile potrzebujesz. Po każdym kroku wróć do zadania i sprawdź wynik.
5. Sprawdź rozumienie, nie tylko uruchomienie
Dalej na swoim koncie
Rozgrzewki, quiz i zadania są w biurku ucznia.
Teoria jest otwarta dla wszystkich. Żeby rozwiązywać zadania, zapisywać szkice i widzieć swój postęp, zaloguj się.
Zaloguj się →