Dziedziczenie w C#

1. Wprowadzenie

Dziedziczenie jest jedną z podstawowych cech programowania obiektowego (OOP). Pozwala na tworzenie nowych klas na bazie istniejących klas, dzięki czemu można:

  • Ponownie wykorzystywać kod (code reuse),
  • Rozszerzać funkcjonalność istniejących klas,
  • Tworzyć hierarchie klas i modele rzeczywistych obiektów.

W C# klasa bazowa (base class) przekazuje swoje pola, właściwości i metody klasie pochodnej (derived class).


2. Podstawowa składnia dziedziczenia

Użycie klas

Klasa Pies automatycznie odziedziczyła pole i metodę klasy Zwierze.


3. Typy dziedziczenia w C#

3.1 Pojedyncze dziedziczenie

W C# obowiązuje pojedyncze dziedziczenie klas, co oznacza, że klasa pochodna może dziedziczyć tylko po jednej klasie bazowej:

Próba dziedziczenia po więcej niż jednej klasie:

3.2 Dziedziczenie interfejsów

C# pozwala implementować wiele interfejsów, ale to nie jest dziedziczenie klas, tylko implementacja kontraktów. (Omówimy tylko w kontekście klas pochodnych).


4. Modyfikatory dostępu a dziedziczenie

Modyfikator Widoczność dla klasy pochodnej
public Widoczne wszędzie
protected Widoczne tylko w klasie bazowej i klasach pochodnych
private Nie widoczne w klasach pochodnych
internal Widoczne w obrębie tego samego assembly
protected internal Widoczne w klasach pochodnych i w assembly

Przykład:


5. Konstruktory w dziedziczeniu

  • Klasę pochodną można inicjalizować za pomocą konstruktora klasy bazowej.
  • W C# używa się do tego słowa kluczowego base.

Użycie:


6. Metody wirtualne i override

Dziedziczenie pozwala nadpisywać metody klasy bazowej:

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

7. Typy referencyjne a dziedziczenie

  • Wszystkie obiekty klas w C# są typami referencyjnymi.
  • Przypisanie obiektu klasy pochodnej do zmiennej klasy bazowej jest dopuszczalne:
  • Pozwala to na tworzenie polimorficznych kolekcji (więcej w polimorfizmie).

8. Finalne i abstrakcyjne klasy

8.1 Sealed (klasa zapieczętowana)

  • Klasa sealed nie może być dziedziczona.

8.2 Abstrakcyjna klasa

  • Klasa abstrakcyjna nie może być instancjonowana, ale może mieć metody wirtualne i pola:

9. Dobre praktyki dziedziczenia

  1. Używaj dziedziczenia tylko wtedy, gdy istnieje „jest rodzajem” (is-a) – np. Pies jest zwierzęciem.
  2. Preferuj kompozycję (posiadanie obiektów w klasie) jeśli dziedziczenie nie jest naturalne.
  3. Modyfikatory protected i private pomagają chronić dane klasy bazowej.
  4. Nadpisuj metody tylko tam, gdzie jest to konieczne.
  5. sealed – zabezpiecz klasy, których nie chcesz rozszerzać.