Utilizziamo i cookie per migliorare la tua esperienza sul sito
CodeWorlds

Dziedziczenie - ewolucja gatunków

Witaj znowu, @name! Darwin tutaj z fascynującym tematem.

W poprzednich lekcjach nauczyłeś/aś się tworzyć klasy reprezentujące gatunki. Ale w naturze gatunki nie są izolowane - są częścią hierarchii taksonomicznej! Lwy i tygrysy to różne gatunki, ale oba są kotowatymi. Kotowate i psowate to różne rodziny, ale oba są ssakami.

W programowaniu obiektowym ta hierarchia to dziedziczenie (inheritance) - jeden z najpo tężniejszych mechanizmów OOP!

Czym jest dziedziczenie?

Dziedziczenie pozwala tworzyć nowe klasy na podstawie istniejących:

  • Klasa bazowa (parent, superclass) - ogólniejsza, np. "Ssak"
  • Klasa pochodna (child, subclass) - bardziej specyficzna, np. "Lew"

Klasa pochodna dziedziczy atrybuty i metody klasy bazowej, a następnie może:

  • ✅ Używać dziedziczonych metod bez zmian
  • Rozszerzać klasy bazowe (dodawać nowe metody)
  • Nadpisywać metody (override) - zmienić zachowanie
1# Klasa bazowa - ogólny Ssak
2class Mammal:
3    def __init__(self, name):
4        self.name = name
5
6    def breathe(self):
7        return f"{self.name} oddycha powietrzem"
8
9    def move(self):
10        return f"{self.name} porusza się"
11
12# Klasa pochodna - Lew dziedziczy z Mammal
13class Lion(Mammal):
14    def __init__(self, name, pride_name):
15        super().__init__(name)  # Wywołaj konstruktor rodzica
16        self.pride_name = pride_name  # Dodaj własny atrybut
17
18    def roar(self):
19        """Nowa metoda - tylko dla lwów"""
20        return f"{self.name} ryczy: RRROAAR!"
21
22    def move(self):
23        """Nadpisanie metody rodzica"""
24        return f"{self.name} biegnie przez sawannę"
25
26# Użycie
27simba = Lion("Simba", "Pride Rock")
28
29# Dziedziczone z Mammal
30print(simba.breathe())  # "Simba oddycha powietrzem"
31
32# Nadpisane w Lion
33print(simba.move())  # "Simba biegnie przez sawannę"
34
35# Własna metoda Lion
36print(simba.roar())  # "Simba ryczy: RRROAAR!"
37
38# Własny atrybut Lion
39print(simba.pride_name)  # "Pride Rock"

Składnia dziedziczenia

1# Podstawowa składnia
2class ChildClass(ParentClass):
3    pass
4
5# Dziedziczenie z rozszerzeniem
6class Animal:
7    def eat(self):
8        return "Jem"
9
10class Dog(Animal):  # Dog dziedziczy z Animal
11    def bark(self):
12        return "Hau hau!"
13
14dog = Dog()
15print(dog.eat())   # Dziedziczone: "Jem"
16print(dog.bark())  # Własne: "Hau hau!"

Funkcja
super()

super()
pozwala odwołać się do klasy bazowej - używaj jej do:

  • Wywołania konstruktora rodzica
  • Rozszerzenia metody rodzica (nie całkowitego nadpisania)
1class Animal:
2    def __init__(self, name, age):
3        self.name = name
4        self.age = age
5        print(f"Tworzę zwierzę: {name}")
6
7    def describe(self):
8        return f"{self.name}, wiek: {self.age}"
9
10class Bird(Animal):
11    def __init__(self, name, age, wingspan):
12        # Wywołaj konstruktor Animal
13        super().__init__(name, age)
14        # Dodaj własny atrybut
15        self.wingspan = wingspan
16        print(f"Rozpiętość skrzydeł: {wingspan}m")
17
18    def describe(self):
19        # Rozszerz metodę rodzica
20        base_desc = super().describe()  # Wywołaj Animal.describe()
21        return f"{base_desc}, rozpiętość: {self.wingspan}m"
22
23eagle = Bird("Orzeł", 5, 2.3)
24# Drukuje:
25# Tworzę zwierzę: Orzeł
26# Rozpiętość skrzydeł: 2.3m
27
28print(eagle.describe())
29# "Orzeł, wiek: 5, rozpiętość: 2.3m"

Nadpisywanie metod (Method Overriding)

Klasa pochodna może całkowicie zastąpić metodę rodzica:

1class Animal:
2    def speak(self):
3        return "Zwierzę wydaje dźwięk"
4
5class Dog(Animal):
6    def speak(self):
7        """Nadpisz całkowicie"""
8        return "Hau hau!"  # Całkowicie nowe zachowanie
9
10class Cat(Animal):
11    def speak(self):
12        """Nadpisz całkowicie"""
13        return "Miau!"
14
15dog = Dog()
16cat = Cat()
17
18print(dog.speak())  # "Hau hau!" - nie "Zwierzę wydaje dźwięk"
19print(cat.speak())  # "Miau!"

Hierarchia klas - drzewo taksonomiczne

W naturze hierarchia jest głęboka: Królestwo → Typ → Klasa → Rząd → Rodzina → Rodzaj → Gatunek

1# 1. Królestwo Animalia
2class Animal:
3    kingdom = "Animalia"
4
5    def __init__(self, name):
6        self.name = name
7
8    def is_alive(self):
9        return True
10
11    def __str__(self):
12        return f"{self.name} ({self.__class__.__name__})"
13
14# 2. Typ Chordata
15class Chordate(Animal):
16    phylum = "Chordata"
17
18    def has_backbone(self):
19        return True
20
21# 3. Klasa Mammalia (Ssaki)
22class Mammal(Chordate):
23    class_name = "Mammalia"
24
25    def __init__(self, name, fur_color):
26        super().__init__(name)
27        self.fur_color = fur_color
28
29    def nurse_young(self):
30        return f"{self.name} karmi młode mlekiem"
31
32    def regulate_temperature(self):
33        return f"{self.name} utrzymuje stałą temperaturę ciała"
34
35# 4. Rząd Carnivora (Drapieżniki)
36class Carnivore(Mammal):
37    order = "Carnivora"
38
39    def __init__(self, name, fur_color, hunting_style):
40        super().__init__(name, fur_color)
41        self.hunting_style = hunting_style
42
43    def hunt(self):
44        return f"{self.name} poluje używając: {self.hunting_style}"
45
46# 5. Rodzina Felidae (Kotowate)
47class Feline(Carnivore):
48    family = "Felidae"
49
50    def retract_claws(self):
51        return f"{self.name} chowa pazury"
52
53    def purr(self):
54        return f"{self.name} mruczy"
55
56# 6. Gatunek Panthera leo (Lew)
57class Lion(Feline):
58    species = "Panthera leo"
59
60    def __init__(self, name, fur_color, pride_name):
61        super().__init__(name, fur_color, "polowanie stadne")
62        self.pride_name = pride_name
63
64    def roar(self):
65        return f"{self.name} ryczy głośno!"
66
67    def lead_pride(self):
68        return f"{self.name} przewodzi stadzie {self.pride_name}"
69
70# Użycie - lew ma dostęp do WSZYSTKICH metod hierarchii!
71simba = Lion("Simba", "złoty", "Pride Rock")
72
73# Z Animal
74print(simba.is_alive())  # True
75
76# Z Chordate
77print(simba.has_backbone())  # True
78
79# Z Mammal
80print(simba.nurse_young())  # "Simba karmi młode mlekiem"
81print(simba.regulate_temperature())  # "Simba utrzymuje stałą temperaturę ciała"
82
83# Z Carnivore
84print(simba.hunt())  # "Simba poluje używając: polowanie stadne"
85
86# Z Feline
87print(simba.retract_claws())  # "Simba chowa pazury"
88print(simba.purr())  # "Simba mruczy"
89
90# Własne Lion
91print(simba.roar())  # "Simba ryczy głośno!"
92print(simba.lead_pride())  # "Simba przewodzi stadzie Pride Rock"
93
94# Atrybuty
95print(simba.kingdom)  # "Animalia"
96print(simba.species)  # "Panthera leo"
97print(simba.fur_color)  # "złoty"

Sprawdzanie relacji klas

Python oferuje funkcje do sprawdzania hierarchii:

1class Animal:
2    pass
3
4class Mammal(Animal):
5    pass
6
7class Lion(Mammal):
8    pass
9
10simba = Lion()
11
12# isinstance() - sprawdź czy obiekt jest instancją klasy
13print(isinstance(simba, Lion))    # True
14print(isinstance(simba, Mammal))  # True - Lion dziedziczy z Mammal
15print(isinstance(simba, Animal))  # True - Lion dziedziczy z Animal (przez Mammal)
16print(isinstance(simba, str))     # False
17
18# issubclass() - sprawdź czy klasa dziedziczy z innej klasy
19print(issubclass(Lion, Mammal))   # True
20print(issubclass(Lion, Animal))   # True
21print(issubclass(Mammal, Lion))   # False
22print(issubclass(Lion, Lion))     # True - klasa jest podklasą samej siebie
23
24# type() - zwróć dokładny typ
25print(type(simba))  # <class '__main__.Lion'>
26print(type(simba) == Lion)    # True
27print(type(simba) == Mammal)  # False - simba to Lion, nie Mammal

Wielodziedziczenie (Multiple Inheritance)

Python pozwala dziedziczyć z wielu klas naraz - klasa może mieć wielu rodziców!

1class Swimmer:
2    def swim(self):
3        return f"{self.name} pływa"
4
5class Flyer:
6    def fly(self):
7        return f"{self.name} lata"
8
9class Walker:
10    def walk(self):
11        return f"{self.name} chodzi"
12
13# Duck dziedziczy z trzech klas!
14class Duck(Swimmer, Flyer, Walker):
15    def __init__(self, name):
16        self.name = name
17
18    def quack(self):
19        return f"{self.name}: Kwa kwa!"
20
21donald = Duck("Donald")
22
23# Ma dostęp do metod ze wszystkich klas bazowych
24print(donald.swim())   # "Donald pływa"
25print(donald.fly())    # "Donald lata"
26print(donald.walk())   # "Donald chodzi"
27print(donald.quack())  # "Donald: Kwa kwa!"

MRO - Method Resolution Order

Gdy klasa dziedziczy z wielu rodziców, Python używa MRO (Method Resolution Order), aby określić kolejność szukania metod:

1class A:
2    def method(self):
3        return "A"
4
5class B(A):
6    def method(self):
7        return "B"
8
9class C(A):
10    def method(self):
11        return "C"
12
13class D(B, C):  # Dziedziczy z B i C
14    pass
15
16d = D()
17print(d.method())  # "B" - Python szuka: D → B → C → A
18
19# Sprawdź MRO
20print(D.__mro__)
21# (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>,
22#  <class '__main__.A'>, <class 'object'>)
23
24# Lub czytelniej:
25print(D.mro())

Zasada: Python przeszukuje klasy od lewej do prawej, od najbardziej specyficznej do najbardziej ogólnej.

Safari przykład - hierarchia gatunków z obserwacjami

1class Species:
2    """
3    Klasa bazowa dla wszystkich gatunków w katalogu Safari
4    """
5
6    kingdom = "Animalia"
7    total_species_count = 0
8
9    def __init__(self, scientific_name, common_name, habitat):
10        self.scientific_name = scientific_name
11        self.common_name = common_name
12        self.habitat = habitat
13        self.observations = []
14
15        Species.total_species_count += 1
16
17    def add_observation(self, date, location, count, notes=""):
18        """Dodaj obserwację w terenie"""
19        self.observations.append({
20            "date": date,
21            "location": location,
22            "count": count,
23            "notes": notes
24        })
25
26    def get_total_observed(self):
27        """Łączna liczba zaobserwowanych osobników"""
28        return sum(obs["count"] for obs in self.observations)
29
30    def describe(self):
31        """Podstawowy opis gatunku"""
32        return f"{self.common_name} ({self.scientific_name})"
33
34    def __str__(self):
35        return self.describe()
36
37class Mammal(Species):
38    """
39    Klasa reprezentująca ssaki - rozszerza Species
40    """
41
42    class_name = "Mammalia"
43
44    def __init__(self, scientific_name, common_name, habitat, fur_color, gestation_days):
45        # Wywołaj konstruktor Species
46        super().__init__(scientific_name, common_name, habitat)
47        # Dodaj atrybuty specyficzne dla ssaków
48        self.fur_color = fur_color
49        self.gestation_days = gestation_days
50
51    def nurse_young(self):
52        """Ssaki karmią młode mlekiem"""
53        return f"{self.common_name} karmi młode mlekiem przez {self.gestation_days // 30} miesięcy"
54
55    def describe(self):
56        """Rozszerz opis o informacje o ssakach"""
57        base = super().describe()  # Wywołaj Species.describe()
58        return f"{base} | Ssak | Futro: {self.fur_color}"
59
60class Bird(Species):
61    """
62    Klasa reprezentująca ptaki
63    """
64
65    class_name = "Aves"
66
67    def __init__(self, scientific_name, common_name, habitat, wingspan_m, can_fly=True):
68        super().__init__(scientific_name, common_name, habitat)
69        self.wingspan_m = wingspan_m
70        self.can_fly = can_fly
71
72    def lay_eggs(self):
73        return f"{self.common_name} składa jaja"
74
75    def describe(self):
76        base = super().describe()
77        flight_status = "latający" if self.can_fly else "nielotny"
78        return f"{base} | Ptak {flight_status} | Rozpiętość: {self.wingspan_m}m"
79
80class Carnivore(Mammal):
81    """
82    Drapieżniki - dziedziczą z Mammal
83    """
84
85    order = "Carnivora"
86
87    def __init__(self, scientific_name, common_name, habitat, fur_color,
88                 gestation_days, hunting_style, pack_hunter=False):
89        super().__init__(scientific_name, common_name, habitat, fur_color, gestation_days)
90        self.hunting_style = hunting_style
91        self.pack_hunter = pack_hunter
92
93    def hunt(self):
94        style = "w stadzie" if self.pack_hunter else "samotnie"
95        return f"{self.common_name} poluje {style} używając: {self.hunting_style}"
96
97    def calculate_danger_level(self):
98        """Oblicz poziom niebezpieczeństwa (1-10)"""
99        base_danger = 5
100        if self.pack_hunter:
101            base_danger += 3
102        if "zasadzka" in self.hunting_style:
103            base_danger += 2
104        return min(10, base_danger)
105
106    def describe(self):
107        base = super().describe()
108        danger = self.calculate_danger_level()
109        return f"{base} | Drapieżnik | Niebezp.: {danger}/10"
110
111class Herbivore(Mammal):
112    """
113    Roślinożercy - dziedziczą z Mammal
114    """
115
116    def __init__(self, scientific_name, common_name, habitat, fur_color,
117                 gestation_days, diet_type):
118        super().__init__(scientific_name, common_name, habitat, fur_color, gestation_days)
119        self.diet_type = diet_type  # "liście", "trawa", "owoce"
120
121    def graze(self):
122        return f"{self.common_name} je {self.diet_type}"
123
124    def describe(self):
125        base = super().describe()
126        return f"{base} | Roślinożerca | Dieta: {self.diet_type}"
127
128class Feline(Carnivore):
129    """
130    Kotowate - dziedziczą z Carnivore
131    """
132
133    family = "Felidae"
134
135    def __init__(self, scientific_name, common_name, habitat, fur_color,
136                 gestation_days, has_mane=False, pride_size=1):
137        super().__init__(
138            scientific_name, common_name, habitat, fur_color,
139            gestation_days, "zasadzka i pościg", pack_hunter=(pride_size > 1)
140        )
141        self.has_mane = has_mane
142        self.pride_size = pride_size
143
144    def retract_claws(self):
145        return f"{self.common_name} chowa ostre pazury"
146
147    def stalk_prey(self):
148        return f"{self.common_name} skrada się cicho do zdobyczy"
149
150    def describe(self):
151        base = super().describe()
152        social = f"stadne ({self.pride_size})" if self.pride_size > 1 else "samotne"
153        return f"{base} | Kotowate | {social}"
154
155class Canine(Carnivore):
156    """
157    Psowate - dziedziczą z Carnivore
158    """
159
160    family = "Canidae"
161
162    def __init__(self, scientific_name, common_name, habitat, fur_color,
163                 gestation_days, pack_size=1):
164        super().__init__(
165            scientific_name, common_name, habitat, fur_color,
166            gestation_days, "pościg na dystansie", pack_hunter=(pack_size > 1)
167        )
168        self.pack_size = pack_size
169
170    def howl(self):
171        return f"{self.common_name} wyje do stada"
172
173    def track_scent(self):
174        return f"{self.common_name} tropi zdobycz po zapachu"
175
176    def describe(self):
177        base = super().describe()
178        social = f"wataha ({self.pack_size})" if self.pack_size > 1 else "samotne"
179        return f"{base} | Psowate | {social}"
180
181# === DEMONSTRACJA - Tworzenie hierarchii Safari ===
182
183print("=== KATALOG GATUNKÓW SAFARI - HIERARCHIA ===\n")
184
185# Kotowate
186lion = Feline(
187    scientific_name="Panthera leo",
188    common_name="Lew",
189    habitat="sawanna",
190    fur_color="złoty",
191    gestation_days=110,
192    has_mane=True,
193    pride_size=15
194)
195
196leopard = Feline(
197    scientific_name="Panthera pardus",
198    common_name="Lampart",
199    habitat="sawanna i lasy",
200    fur_color="żółty w czarne plamy",
201    gestation_days=90,
202    has_mane=False,
203    pride_size=1  # Samotnik
204)
205
206# Psowate
207wild_dog = Canine(
208    scientific_name="Lycaon pictus",
209    common_name="Likaon",
210    habitat="sawanna",
211    fur_color="pstrokaty",
212    gestation_days=70,
213    pack_size=20
214)
215
216# Roślinożercy
217elephant = Herbivore(
218    scientific_name="Loxodonta africana",
219    common_name="Słoń afrykański",
220    habitat="sawanna",
221    fur_color="szary",
222    gestation_days=645,  # Najdłuższa ciąża!
223    diet_type="liście, kora, trawa"
224)
225
226giraffe = Herbivore(
227    scientific_name="Giraffa camelopardalis",
228    common_name="Żyrafa",
229    habitat="sawanna",
230    fur_color="żółty w brązowe plamy",
231    gestation_days=440,
232    diet_type="liście akacji"
233)
234
235# Ptaki
236eagle = Bird(
237    scientific_name="Aquila rapax",
238    common_name="Orzeł stepowy",
239    habitat="sawanna",
240    wingspan_m=2.1,
241    can_fly=True
242)
243
244# Dodaj obserwacje
245lion.add_observation("2024-01-15", "Serengeti", 12, "Stado polujące na gnu")
246lion.add_observation("2024-01-20", "Masai Mara", 8, "Rodzina z młodymi")
247leopard.add_observation("2024-01-16", "Obszar skalny", 1, "Samotny samiec")
248wild_dog.add_observation("2024-01-18", "Savuti", 18, "Wataha polująca")
249elephant.add_observation("2024-01-17", "Amboseli", 45, "Duże stado przy wodopoju")
250giraffe.add_observation("2024-01-19", "Tarangire", 23, "Żyją żyrafą akacjami")
251eagle.add_observation("2024-01-21", "Niebo nad sawanną", 3, "Para z młodym")
252
253# Wyświetl opisy - każdy używa swojej wersji describe()
254print("🦁 LEW:")
255print(f"  {lion.describe()}")
256print(f"  {lion.hunt()}")
257print(f"  {lion.stalk_prey()}")
258print(f"  {lion.retract_claws()}")
259print(f"  {lion.nurse_young()}")
260print(f"  Obserwacje: {lion.get_total_observed()} osobników")
261
262print(f"\n🐆 LAMPART:")
263print(f"  {leopard.describe()}")
264print(f"  {leopard.hunt()}")
265print(f"  Poziom niebezpieczeństwa: {leopard.calculate_danger_level()}/10")
266
267print(f"\n🐺 LIKAON:")
268print(f"  {wild_dog.describe()}")
269print(f"  {wild_dog.hunt()}")
270print(f"  {wild_dog.howl()}")
271print(f"  {wild_dog.track_scent()}")
272
273print(f"\n🐘 SŁOŃ:")
274print(f"  {elephant.describe()}")
275print(f"  {elephant.graze()}")
276print(f"  Obserwacje: {elephant.get_total_observed()} osobników")
277
278print(f"\n🦒 ŻYRAFA:")
279print(f"  {giraffe.describe()}")
280print(f"  {giraffe.graze()}")
281
282print(f"\n🦅 ORZEŁ:")
283print(f"  {eagle.describe()}")
284print(f"  {eagle.lay_eggs()}")
285
286# Sprawdź hierarchię
287print(f"\n=== HIERARCHIA KLAS ===")
288print(f"Lew dziedziczy z Feline? {isinstance(lion, Feline)}")
289print(f"Lew dziedziczy z Carnivore? {isinstance(lion, Carnivore)}")
290print(f"Lew dziedziczy z Mammal? {isinstance(lion, Mammal)}")
291print(f"Lew dziedziczy z Species? {isinstance(lion, Species)}")
292print(f"Lew dziedziczy z Bird? {isinstance(lion, Bird)}")
293
294print(f"\nMRO Feline: {[cls.__name__ for cls in Feline.mro()]}")
295# ['Feline', 'Carnivore', 'Mammal', 'Species', 'object']
296
297print(f"\n=== STATYSTYKI ===")
298print(f"Łączna liczba gatunków w katalogu: {Species.total_species_count}")
299
300# Polimorfizm - każdy gatunek ma swoją implementację describe()
301print(f"\nWszystkie gatunki:")
302all_animals = [lion, leopard, wild_dog, elephant, giraffe, eagle]
303for animal in all_animals:
304    print(f"  - {animal.describe()}")

Praktyczne zasady dziedziczenia

1. Kiedy używać dziedziczenia?

Użyj dziedziczenia gdy:

  • Relacja "jest" (is-a): Lew jest Ssakiem ✓
  • Chcesz reużyć kod z klasy bazowej
  • Tworzysz hierarchię typów

NIE używaj dziedziczenia gdy:

  • Relacja "ma" (has-a): Samochód ma Silnik (użyj kompozycji!)
  • Klasy nie mają wspólnej natury
  • Chcesz tylko pożyczyć kilka metod
1# ✅ Dobre - relacja "jest"
2class Animal:
3    pass
4
5class Dog(Animal):  # Pies JEST zwierzęciem
6    pass
7
8# ❌ Złe - relacja "ma"
9class Engine:
10    def start(self):
11        return "Silnik uruchomiony"
12
13class Car(Engine):  # NIE! Samochód NIE JEST silnikiem!
14    pass
15
16# ✅ Dobre - kompozycja
17class Car:
18    def __init__(self):
19        self.engine = Engine()  # Samochód MA silnik
20
21    def start(self):
22        return self.engine.start()

2. Zasada Liskov Substitution Principle (LSP)

Obiekt klasy pochodnej powinien móc zastąpić obiekt klasy bazowej bez zmiany poprawności programu.

1def make_sound(animal):
2    """Funkcja przyjmuje dowolne Animal"""
3    print(animal.speak())
4
5class Animal:
6    def speak(self):
7        return "..."
8
9class Dog(Animal):
10    def speak(self):
11        return "Hau!"
12
13class Cat(Animal):
14    def speak(self):
15        return "Miau!"
16
17# LSP - Dog i Cat mogą zastąpić Animal
18make_sound(Dog())  # "Hau!" - działa
19make_sound(Cat())  # "Miau!" - działa

3. Unikaj głębokiej hierarchii

1# ❌ Złe - zbyt głęboka hierarchia
2class A:
3    pass
4class B(A):
5    pass
6class C(B):
7    pass
8class D(C):
9    pass
10class E(D):
11    pass
12class F(E):  # 6 poziomów!
13    pass
14
15# ✅ Dobre - płaska, zrozumiała hierarchia
16class Animal:
17    pass
18
19class Mammal(Animal):
20    pass
21
22class Lion(Mammal):
23    pass
24# 3 poziomy - czytelne!

Podsumowanie

W tej lekcji nauczyłeś/aś się:

  • ✅ Czym jest dziedziczenie i dlaczego jest potężne
  • ✅ Jak tworzyć klasy pochodne z
    class Child(Parent)
  • ✅ Używania
    super()
    do wywołania metod rodzica
  • ✅ Nadpisywania i rozszerzania metod
  • ✅ Budowania hierarchii klas (drzewo taksonomiczne)
  • ✅ Sprawdzania relacji z
    isinstance()
    i
    issubclass()
  • ✅ Wielodziedziczenia i MRO
  • ✅ Praktycznych zasad: kiedy używać dziedziczenia, a kiedy nie

Checkpoint

Przed przejściem dalej:

  • [ ] Rozumiesz różnicę między klasą bazową a pochodną
  • [ ] Potrafisz użyć
    super()
    w konstruktorze
  • [ ] Wiesz jak nadpisać metodę rodzica
  • [ ] Rozumiesz hierarchię i dziedziczenie wielu poziomów
  • [ ] Znasz różnicę między relacją "jest" (dziedziczenie) a "ma" (kompozycja)

Analogia Safari: Hierarchia klas to drzewo ewolucyjne - każdy potomek dziedziczy cechy przodków, ale rozwija własne unikalne adaptacje! 🌳🦁🐘

W następnej lekcji Darwin nauczy Cię enkapsulacji - jak chronić wrażliwe dane gatunków przed nieautoryzowanym dostępem! 🔒📊

Vai a CodeWorlds