Polimorfizm w C#

1. Wprowadzenie

Polimorfizm to jedna z fundamentalnych cech programowania obiektowego (OOP). Pochodzi od greckiego: poly = wiele, morph = forma, co oznacza wiele form.

W kontekście C# polimorfizm pozwala:

  • używać tej samej nazwy metody w różnych klasach,
  • wywoływać metody klasy pochodnej poprzez referencję klasy bazowej,
  • pisać kod bardziej elastyczny i skalowalny.

Polimorfizm dzieli się głównie na polimorfizm statyczny (kompilacyjny) i polimorfizm dynamiczny (wywołania w czasie działania programu).


2. Polimorfizm statyczny (compile-time)

Polimorfizm statyczny polega na tym, że decyzja, którą metodę wywołać, jest podejmowana w czasie kompilacji.

2.1 Przeciążanie metod (method overloading)

  • Ta sama nazwa metody, różne parametry (liczba, typ, kolejność).

Zasady przeciążania metod:

  • Różna liczba parametrów,
  • Różne typy parametrów,
  • Różna kolejność parametrów.

Nie można przeciążać metod tylko przez zmianę typu zwracanego.


2.2 Przeciążanie operatorów (operator overloading)

C# pozwala nadpisywać operatory dla własnych typów klas lub struktur:


3. Polimorfizm dynamiczny (run-time)

Polimorfizm dynamiczny polega na tym, że decyzja, którą metodę wywołać, jest podejmowana w czasie działania programu.

W C# osiąga się go dzięki dziedziczeniu, metodom wirtualnym i nadpisywaniu metod.

3.1 Metody wirtualne i override

  • virtual – metoda klasy bazowej, którą można nadpisać,
  • override – metoda klasy pochodnej, która nadpisuje metodę bazową.

Pomimo, że zmienne są typu Zwierze, wywoływana jest metoda klasy pochodnej. To polimorfizm w czasie wykonania.


3.2 Sealed i new

  • sealed – uniemożliwia dalsze nadpisywanie metod.
  • new – ukrywa metodę klasy bazowej, ale nie nadpisuje jej w sensie polimorfizmu dynamicznego.

Użycie new powoduje ukrycie metody, a nie prawdziwe nadpisanie.


3.3 Polimorfizm i kolekcje

Polimorfizm umożliwia tworzenie kolekcji różnych obiektów klas pochodnych, które można traktować jak obiekty klasy bazowej:


4. Podsumowanie rodzajów polimorfizmu

Typ polimorfizmu Kiedy decyzja wywołania jest podejmowana Przykład w C#
Statyczny (compile-time) Podczas kompilacji Przeciążanie metod, operatorów
Dynamiczny (run-time) Podczas działania programu Metody wirtualne i override

5. Dobre praktyki polimorfizmu

  1. Używaj metod wirtualnych i override dla funkcji, które mogą mieć różne zachowania w klasach pochodnych.
  2. Nie nadużywaj new – może prowadzić do nieintuicyjnych wyników.
  3. Stosuj polimorfizm w kolekcjach i hierarchiach klas, aby kod był elastyczny i rozszerzalny.
  4. Polimorfizm statyczny (przeciążanie) – używaj do zwiększenia czytelności i wygody korzystania z klasy.
  5. W polimorfizmie dynamicznym zwracaj uwagę na bezpieczeństwo typów i unikaj rzutowania, jeśli to możliwe.