Dziedziczenie

Mechanizm pozwalający klasie przejmować właściwości i metody innej klasy. Ułatwia ponowne wykorzystanie kodu i tworzenie hierarchii obiektów.

Dziedziczenie to mechanizm programowania obiektowego (OOP), w którym jedna klasa (potomna, zwana podklasą lub klasą pochodną) przejmuje pola i metody innej klasy (bazowej, czyli nadklasy). Dzięki temu nie przepisujesz tego samego kodu w kółko — wspólną logikę umieszczasz raz w klasie bazowej, a klasy potomne dostają ją w spadku i mogą dorzucić własne rozszerzenia albo nadpisać to, co odziedziczyły.

Mówiąc obrazowo: Pies i Kot to różne stworzenia, ale oba są Zwierze. Zamiast dwa razy definiować, że zwierzę je, śpi i ma imię, robisz to raz w klasie Zwierze, a Pies i Kot tylko z niej dziedziczą. To buduje hierarchię „jest rodzajem” (relacja is-a): pies jest zwierzęciem.

Do czego to służy w praktyce

Dziedziczenie pozwala porządkować kod w hierarchie i unikać duplikacji. Idzie zwykle w parze z polimorfizmem — możesz traktować obiekty klas potomnych tak, jakby były obiektami klasy bazowej, a one i tak zachowają się po swojemu (np. każde zwierzę „wydaje dźwięk”, ale pies szczeka, a kot miauczy).

Konkretny przykład z prawdziwego świata: w Pythonie, jeśli piszesz aplikację webową w Django, każdy Twój model dziedziczy z models.Model:

  1. class Artykul(models.Model): — Twoja klasa od razu dostaje gotową obsługę zapisu do bazy, walidację, metody typu save() czy delete().
  2. Ty dopisujesz tylko to, co specyficzne dla artykułu: pola tytul, tresc, data_publikacji.

Nie piszesz logiki bazodanowej od zera — bierzesz ją w spadku. Podobnie w Javie nadpisujesz toString() z klasy Object, z której dziedziczy każda klasa.

Częste błędy i mity

  • Nadużywanie dziedziczenia. Początkujący budują głębokie, kilkupiętrowe hierarchie, które potem trudno zmienić. Zasada z branży brzmi: composition over inheritance — często lepiej złożyć obiekt z mniejszych części, niż dziedziczyć po kolejnej klasie.
  • Mylenie is-a z has-a. Samochód nie jest silnikiem — samochód ma silnik. To przypadek na kompozycję, nie dziedziczenie.
  • Problem diamentu. Przy wielodziedziczeniu (kilka klas bazowych) robi się bałagan, dlatego Java czy C# go zabraniają, a oferują w zamian interfejsy. Python pozwala, ale rozwiązuje konflikty przez MRO (Method Resolution Order).

Pojęcia powiązane: polimorfizm, enkapsulacja, abstrakcja (cztery filary OOP), klasa bazowa i potomna, nadpisywanie metod (override), klasy abstrakcyjne, interfejsy oraz kompozycja jako alternatywa.