7.1 Метод super()
Раз вже ми торкнулися ієрархії наслідування, то корисно буде поговорити про нюанси роботи з полями та методами базового класу. Для цього в Python є спеціальний метод super(). Цей метод використовується для виклику методів базового класу всередині дочірнього класу.
У нього є три основних області застосування:
Виклик методів батьківського класу:
Метод super() дозволяє викликати метод батьківського класу з дочірнього класу, не вказуючи явно ім'я батьківського класу. Це особливо корисно при роботі з множинним наслідуванням і допомагає уникати помилок при зміні ієрархії класів.
Ініціалізація базових класів:
super() часто використовується в конструкторі дочірнього класу для виклику конструктора базового класу, що дозволяє ініціалізувати атрибути базового класу в дочірньому класі.
Підтримка множинного наслідування:
У випадку множинного наслідування super() правильно вирішує порядок викликів методів (MRO, Method Resolution Order), що робить його використання переважним перед явним викликом методів батьківських класів. Про це ми поговоримо трохи пізніше.
7.2 Конструктор базового класу
Конструктор базового класу має бути викликаний явно. Здається, що це відбувається автоматично, але насправді це не так. Конструктори базових класів завжди потрібно викликати явно, оскільки дуже часто в них потрібно передати особливі аргументи.
Приклад:
class Animal:
def __init__(self, type, name):
self.type = type
self.name = name
class Dog(Animal):
def __init__(self, name):
super().__init__("Собака", name) # Виклик конструктора базового класу
class Cat(Animal):
def __init__(self, name):
super().__init__("Кішка", name) # Виклик конструктора базового класу
# Створення об'єкта Dog
dog = Dog("Buddy")
print(dog)
У цьому прикладі у конструктора базового класу (Animal) два параметри: тип тварини та його ім'я. А у класів-нащадків тільки по одному — лише ім'я.
Саме в конструкторах класів Dog і Cat приймається рішення, що саме передати в конструктор базового класу — назви типів тварин «Собака» і «Кішка».
Отож:
- Конструктор базового класу потрібно обов'язково викликати в конструкторі класу-нащадка.
- Для цього потрібно використовувати функцію
super(). - Передавати параметр
selfокремо не потрібно — Python підставить його автоматично при виклику методу.
7.3 Використання методу super()
Метод super() в Python можна використовувати не лише в конструкторах, але й в інших методах класів для виклику методів батьківського класу. Це може бути корисно, коли необхідно розширити або модифікувати поведінку методу, визначеного в батьківському класі.
Давайте розглянемо кілька прикладів:
Виклик методу батьківського класу в дочірньому методі
У цьому прикладі метод speak() у класі Dog спочатку викликає метод speak() з класу Animal за допомогою super(), а потім додає власну поведінку.
class Animal:
def speak(self):
return "Some generic animal sound"
class Dog(Animal):
def speak(self):
parent_speech = super().speak() # Виклик методу батьківського класу
return f"{parent_speech} And the dog barks!"
dog = Dog()
print(dog.speak()) # Виведе: Some generic animal sound And the dog barks!
Виклик методу батьківського класу для перевірки стану
У цьому прикладі метод check_health() у класі Dog викликає метод check_health() з класу Animal, щоб додати додаткові перевірки.
class Animal:
def check_health(self):
return "Animal is healthy"
class Dog(Animal):
def check_health(self):
parent_check = super().check_health() # Виклик методу батьківського класу
return f"{parent_check}. Dog needs a walk!"
dog = Dog()
print(dog.check_health()) # Виведе: Animal is healthy. Dog needs a walk!
Виклик методу батьківського класу в методі, що змінює стан
У цьому прикладі метод withdraw() у класі SavingsAccount спочатку перевіряє, чи не перевищено ліміт на зняття коштів, і якщо ні, викликає метод withdraw() з класу BankAccount для виконання операції.
class BankAccount:
def __init__(self, balance):
self.balance = balance
def withdraw(self, amount):
if self.balance >= amount:
self.balance -= amount
return f"Withdrew {amount}. New balance: {self.balance}"
return "Insufficient funds"
class SavingsAccount(BankAccount):
def withdraw(self, amount):
if amount > 1000:
return "Withdrawal limit exceeded"
return super().withdraw(amount) # Виклик методу батьківського класу
savings = SavingsAccount(1500)
print(savings.withdraw(500)) # Виведе: Withdrew 500. New balance: 1000
print(savings.withdraw(1500)) # Виведе: Withdrawal limit exceeded
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ