Наследование и super()
Стройте новые классы на основе существующих, а не с нуля
super() — это способ для дочернего класса сотрудничать с родителем, а не молча его заменять.
- объявлять производный класс через
class Child(Parent):и объяснять связь is-a («является»), - вызывать
__init__родителя (и другие методы) черезsuper(), - переопределять метод и понимать, когда его расширять, а когда заменять,
- выбирать между наследованием и композицией по признаку is-a или has-a,
- читать небольшую иерархию классов и предсказывать, какой метод выполнится.
1. Базовые и производные классы
Вы уже умеете писать отдельный класс с __init__ и методами. Наследование нужно, когда два класса делят много общего поведения и вы не хотите дублировать его дважды. Допустим, вы моделируете животных. У каждого животного есть имя и оно умеет есть; лаять умеют лишь некоторые. Вместо того чтобы повторять код имени и еды в Dog, Cat и Bird, вы кладёте общие части в один базовый класс и позволяете каждому конкретному животному наследоваться от него.
Проверка на наследование — это связь is-a («является»): Dog является Animal, SavingsAccount является BankAccount. Если такое предложение звучит верно, наследование — кандидат. Если же вы сказали бы has-a («имеет»), например Car имеет Engine, — это композиция, о ней в разделе 6.
class Animal: # base / parent class
def __init__(self, name):
self.name = name
def eat(self):
return self.name + " is eating"
class Dog(Animal): # derived / child class -- Dog IS-A Animal
def bark(self):
return "Woof!"
d = Dog("Rex")
print(d.eat()) # inherited from Animal
print(d.bark()) # defined on Dog
Вывод:
Rex is eating
Woof!
Обратите внимание: Dog нигде не объявляет __init__ или eat, но d.eat() работает. Python не нашёл eat в Dog, поэтому заглянул в родителя Animal и взял его. Этот поиск вверх — суть наследования.