Z każdym kolejnym wpisem zagłębiamy się coraz bardziej w temat programowania obiektowego (OOP), a robi się coraz ciekawiej.. Jedna z takich ciekawych koncepcji to dziedziczenie. Dziedziczenie, jak się przekonamy, sporo Nam ułatwia, a także pozwala zaoszczędzić czas. Podobnie jak dziecko dziedziczy cechy po rodzicu, tak samo klasy mogą dziedziczyć po sobie.
Możemy przyjąć że chcemy stworzyć kilka różnych zwierząt. Dziedziczenie pozowli Nam na stworzenie jednej ogólnej klasy, a następnie klas które będą po niej dziedziczyć. Dzięki temu będziemy mogli powielić cechy danej klasy, bez powielania jej kodu, a przy tym dopisać własne. W najprostszym ujęciu, tak to właśnie można wytłumaczyć. Innymi słowy, z klasy bazowej wykorzystujemy co się da, dodatkowo wprowadzając pewne lokalne różnice, które będą specyficzne dla klasy pochodnej.
Dziedziczenie w praktyce
W praktyce stwórzmy sobie jakąś abstrakcyjnąklasę Animal, która będzie definiowała nam jakieś cechy wspólne dla wszystkich zwierząt jakie później powołamy do życia. Czyli będzie to najogólniejsza klasa, która jednak posłuży tylko do dziedziczenia z niej. Nie tworzymy bowiem jakiegoś nieokreślonego zwierzęcia, a właśnie konkretne, które będzie jakimś konkretnym gatunkiem. Zacznijmy od Naszego abstraktu, który zdefiniuje Nam podstawy dla Naszych zwierząt.

Jak widzimy, na razie mamy po prostu klasę, która ma konstruktor. W konstruktorze definiujemy od razu imię i wiek, bo każde zwierzę musi mieć jakieś imię i być w jakimś wieku. Na tym etapie mamy jakieś nieokreślone zwierzę i nie wiemy czy to kot, a może pies. Nie możemy więc mieć takiego obiektu, który jest po prostu zwierzęciem, bo nie wiadomo jakim. Stwórzmy więc na podstawie klasy Animal, jakiegoś przykładowo psa. Normalnie musielibyśmy wszystko przepisywać od nowa by stworzyć psa, bo też musi mieć imię i wiek, ale dzięki klasie Animal - nie musimy. Możemy po prostu wykorzystać dziedziczenie, a klasa dziedzicząca bedzie miała te same właściwości (i ew. metody) co klasa, z której dziedziczy.

Możemy stworzyć sobie Naszą klasę Dog, a w nawiasie, po jej nazwie, podać klasę po jakiej dziedziczymy. W tej sytuacji nie będziemy musieli definiować dla kalsy Dog właściwości name i age, ponieważ odziedziczymy ją po Animal. Zatem dopisujemy tylko przykładową metodę voice odpowiadającą za szczekanie. Teraz możemy sobie przetestować Nasze klasy, stwórzmy jakiegoś psa i zobaczmy czy ma imię i wiek, po ich przypisaniu.
Dziedziczenie - efekty

Jak widzimy, po użyciu klasy Dog i podaniu do jej konstruktora imienia i wieku, mamy psa, który rzeczywiście posiada takie właściwości. Jest to dowód, że w zasadzie klasa Dog, ma właściwości odziedziczone po klasie Animal. My natomiast w klasie Dog nie definiowaliśmy ani właściwości name, ani age. Zaoszczędziliśmy więc pisania drugi raz tego samego, przestrzegając zatem zasady DRY. Co więcej, Nasz pies prósz odziedziczenia właściwości, oczywiście może również używać swojej metody, która pozwala mu szczekać.

Jak widzimy zatem, Nasza klasa dziedzicząca Dog ma dostęp do wszystkich właściwości odziedziczonych po kalasie Animal, a także do metody voide zdefiniowanej w niej samej.
Modyfikacja konstruktora
Dog, jak zauważyliśmy, odziedziczył po klasie bazowej (Animal) konstruktor, dzięki czemu mogliśmy przypisać pieskowi imię i wiek. Może jednak chcemy by pies w swoim konstruktorze miał dodatkową cechę. Przykładowo dodajmy type_of_fur (rodzaj sierści).

W Naszym kodzie zmodyfikowaliśmy odziedziczony konstruktor. Po pierwsze trzeba było napisać jeszcze raz konstruktor, dodając mu w nagłówku nową właściwość. Następnie użyliśmy super(), które pozwala na dostęp do klasy z której dziedziczymy. W tej linijce mówimy zatem, że chcemy użyć konstruktora z klasy rodzica. Po super() piszemy zatem jeszcze raz init i podajemy właściwości używane w klasie bazowej. Co oznacza, że tego wszystkiego chcemy użyć. W następnej linijce dopisujemy Naszą nową właściwość. Innymi słowy po prostu w taki sposób mówimy by użyty został konstruktor klasy bazowej. Tylko dodana zostaje do niego Nasza właściwość type_of_fur.
Na zakończenie dopisujemy w konstrukcji obiektu, jeszczejeden łańcuch znaków uzyskując tak psa z którką sierścią. Następenie wyświetlamy rodzaj sierści obiektu dog1.
Oczywiście klasa rodzica, nie będzie przykładowo miała dostępu do metody klasy dziedziczącej. Dziedziczenie działa w jedną stronę i to dziecko ma dostęp do odziedziczonych właściwości i metod, plus swoich własnych. Tak jak dziecko może mieć swoje włosy, odziedziczone po tacie, ale dodatkowo swój własny kolor oczu, i te cechy są już tylko tego dziecka. Niejako tylko ono nimi zarządza, nie rodzic. Innymi słowy dziedziczenie w Pythonie działa jednokierunkowo: klasa pochodna może korzystać z metod klasy bazowej, ale nie odwrotnie.
Na zadanie domowe stwórz inną klasę, która będzie kolejnym zwierzęciem dziedziczącym po klasie Animal. Niech to kolejne zwierzę też ma swoją metodę i swoją unikalną cechę. Efektami podziel się w komentarzach!
