Przejdź do głównej treści
eLearner.app
Moduł 7 · Lekcja 2 z 426/36 w kursie~12 min
Lekcje modułu (2/4)

Dziedziczenie

Dziedziczenie (inheritance) pozwala utworzyć nową klasę (podklasę), która przejmuje atrybuty i metody istniejącej już klasy (klasy bazowej), i może je rozszerzać lub nadpisywać (override).

Podstawowa składnia

Python
class Animale:
    def __init__(self, nome):
        self.nome = nome

    def saluta(self):
        return f"{self.nome} fa un verso"

class Cane(Animale):       # Cane DZIEDZICZY po Animale
    def saluta(self):       # NADPISANIE metody (override)
        return f"{self.nome} dice WOOF!"

a = Animale("X")
c = Cane("Fido")
a.saluta()      # 'X fa un verso'
c.saluta()      # 'Fido dice WOOF!'

Klasa Cane dziedziczy konstruktor __init__ z klasy Animale bez potrzeby przepisywania go.

super(): wywołanie metody z klasy bazowej

Gdy chcesz rozszerzyć zachowanie metody bazowej (a nie zastąpić ją całkowicie), użyj funkcji super():

Python
class Animale:
    def __init__(self, nome):
        self.nome = nome

class Cane(Animale):
    def __init__(self, nome, razza):
        super().__init__(nome)    # delegacja do klasy bazowej
        self.razza = razza

c = Cane("Fido", "Labrador")
c.nome        # 'Fido'
c.razza       # 'Labrador'

isinstance: sprawdzanie typu

Python
isinstance(c, Cane)        # True
isinstance(c, Animale)     # True (także klasa bazowa)
isinstance(c, str)         # False

Operacja isinstance(x, KlasaBazowa) rozpoznaje również wszystkie podklasy: to właśnie sprawia, że dziedziczenie jest niezwykle użyteczne w implementacji polimorfizmu.

Python
animali = [Cane("Fido", "X"), Animale("Pippo")]
for a in animali:
    print(a.saluta())        # każdy obiekt reaguje we własny sposób

MRO (Method Resolution Order) — przegląd

W przypadku dziedziczenia wielokrotnego, Python decyduje, w jakiej kolejności szukać metody, korzystając z mechanizmu MRO (wyliczanego algorytmem C3). W 95% przypadków wystarczy wiedzieć, że szukanie odbywa się:

  1. najpierw w instancji obiektu,
  2. następnie w jego klasie,
  3. następnie w klasach bazowych w kolejności ich deklaracji.
Python
Cane.__mro__
# (<class 'Cane'>, <class 'Animale'>, <class 'object'>)

object jest klasą bazową dla wszystkich klas w Pythonie 3.

Spróbuj sam

Ćwiczenie#python.m7.l2.e1
Próby: 0Ładowanie...

Mając daną `class Vehicle: def __init__(self, brand): self.brand = brand`, zdefiniuj klasę `Car(Vehicle)` z konstruktorem __init__(self, brand, model) wywołującym super().__init__ i zapisującym self.model. Utwórz `a = Car('Fiat', '500')` i oceń krotkę `(a.brand, a.model)`.

Ładowanie edytora...
Pokaż wskazówkę

Wywołaj super().__init__(brand) a potem self.model = model.

Rozwiązanie dostępne po 3 próbach

Ćwiczenie powtórzeniowe

Ćwiczenie#python.m7.l2.e2
Próby: 0Ładowanie...

Zdefiniuj `class Shape: def area(self): return 0` oraz klasę `Square(Shape)` z konstruktorem __init__(self, side) i metodą area() zwracającą side * side. Utwórz `q = Square(5)` i oceń krotkę `(q.area(), isinstance(q, Shape))`.

Ładowanie edytora...
Pokaż wskazówkę

Zwróć self.side * self.side.

Rozwiązanie dostępne po 3 próbach

Dodatkowe wyzwanie

Ćwiczenie#python.m7.l2.e3
Próby: 0Ładowanie...

Utwórz klasę `Square` dziedziczącą po klasie `Rectangle` (zdefiniowanej poniżej). Konstruktor klasy `Square` musi przyjmować pojedynczy parametr `side` i przekazywać go do `super().__init__(side, side)`. Utwórz obiekt kwadratu o boku `6` w zmiennej `sq` i oceń `sq.area()`.

Ładowanie edytora...
Pokaż wskazówkę

Zadeklaruj klasę Square(Rectangle): i wywołaj super().__init__(side, side) w konstruktorze.

Rozwiązanie dostępne po 3 próbach