7.1 Metoda super()
Skoro rozmawiamy o hierarchii dziedziczenia, warto omówić niuanse pracy z polami i metodami klasy bazowej. W Pythonie jest specjalna metoda super()
. Ta metoda służy do wywoływania metod klasy bazowej wewnątrz klasy pochodnej.
Ma trzy główne zastosowania:
Wywoływanie metod klasy rodzicielskiej:
Metoda super()
pozwala wywołać metodę klasy rodzicielskiej z klasy pochodnej, nie podając jawnie nazwy klasy rodzicielskiej. To jest szczególnie przydatne przy pracy z wielokrotnym dziedziczeniem i pomaga unikać błędów przy zmianie hierarchii klas.
Inicjalizacja klas bazowych:
super()
jest często używane w konstruktorze klasy pochodnej do wywoływania konstruktora klasy bazowej, co umożliwia inicjalizację atrybutów klasy bazowej w klasie pochodnej.
Wsparcie dla wielokrotnego dziedziczenia:
W przypadku wielokrotnego dziedziczenia super()
prawidłowo rozwiązuje porządek wywoływania metod (MRO, Method Resolution Order), co sprawia, że jest preferowane przed jawnym wywoływaniem metod klas rodzicielskich. Omówimy to nieco później.
7.2 Konstruktor klasy bazowej
Konstruktor klasy bazowej musi być wywołany jawnie. Może się wydawać, że dzieje się to automatycznie, ale w rzeczywistości tak nie jest. Konstruktorów klas bazowych zawsze trzeba wywołać jawnie, ponieważ bardzo często trzeba do nich przekazać specjalne argumenty.
Przykład:
class Animal:
def __init__(self, type, name):
self.type = type
self.name = name
class Dog(Animal):
def __init__(self, name):
super().__init__("Pies", name) # Wywołanie konstruktora klasy bazowej
class Cat(Animal):
def __init__(self, name):
super().__init__("Kot", name) # Wywołanie konstruktora klasy bazowej
# Tworzenie obiektu Dog
dog = Dog("Buddy")
print(dog)
W tym przykładzie konstruktor klasy bazowej (Animal)
ma dwa parametry: typ zwierzęcia i jego imię. Klasy dziedziczące mają tylko jeden — tylko imię.
To w konstruktorach klas Dog
i Cat
podjęta jest decyzja, co dokładnie przekazać do konstruktora klasy bazowej — nazwy typów zwierząt „Pies” i „Kot”.
Więc:
- Konstruktor klasy bazowej trzeba koniecznie wywołać w konstruktorze klasy dziedziczącej.
- Do tego trzeba użyć metody
super()
. - Nie trzeba przekazywać parametru
self
osobno — Python zrobi to automatycznie przy wywoływaniu metody.
7.3 Użycie metody super()
Metoda super()
w Pythonie może być używana nie tylko w konstruktorach, ale także w innych metodach klas do wywoływania metod klasy rodzicielskiej. To może być przydatne, gdy trzeba rozszerzyć lub zmodyfikować zachowanie metody zdefiniowanej w klasie rodzicielskiej.
Zobaczmy kilka przykładów:
Wywołanie metody klasy rodzicielskiej w metodzie klasy pochodnej
W tym przykładzie metoda speak()
w klasie Dog
najpierw wywołuje metodę speak()
z klasy Animal
za pomocą super()
, a potem dodaje własne zachowanie.
class Animal:
def speak(self):
return "Jakieś ogólne dźwięki zwierzęcia"
class Dog(Animal):
def speak(self):
parent_speech = super().speak() # Wywołanie metody klasy rodzicielskiej
return f"{parent_speech} A pies szczeka!"
dog = Dog()
print(dog.speak()) # Wyświetli: Jakieś ogólne dźwięki zwierzęcia A pies szczeka!
Wywołanie metody klasy rodzicielskiej do sprawdzenia stanu
W tym przykładzie metoda check_health()
w klasie Dog
wywołuje metodę check_health()
z klasy Animal
, aby dodać dodatkowe sprawdzenia.
class Animal:
def check_health(self):
return "Zwierzę jest zdrowe"
class Dog(Animal):
def check_health(self):
parent_check = super().check_health() # Wywołanie metody klasy rodzicielskiej
return f"{parent_check}. Pies potrzebuje spaceru!"
dog = Dog()
print(dog.check_health()) # Wyświetli: Zwierzę jest zdrowe. Pies potrzebuje spaceru!
Wywołanie metody klasy rodzicielskiej w metodzie zmieniającej stan
W tym przykładzie metoda withdraw()
w klasie SavingsAccount
najpierw sprawdza, czy limit wypłat nie jest przekroczony, a jeśli nie, wywołuje metodę withdraw()
z klasy BankAccount
do wykonania operacji.
class BankAccount:
def __init__(self, balance):
self.balance = balance
def withdraw(self, amount):
if self.balance >= amount:
self.balance -= amount
return f"Wypłacono {amount}. Nowe saldo: {self.balance}"
return "Niewystarczające środki"
class SavingsAccount(BankAccount):
def withdraw(self, amount):
if amount > 1000:
return "Przekroczono limit wypłat"
return super().withdraw(amount) # Wywołanie metody klasy rodzicielskiej
savings = SavingsAccount(1500)
print(savings.withdraw(500)) # Wyświetli: Wypłacono 500. Nowe saldo: 1000
print(savings.withdraw(1500)) # Wyświetli: Przekroczono limit wypłat
GO TO FULL VERSION