>…·····def need_a_push(self):
>…·········print("A little help here?")
>…
Далее создадим объекты классов Car и Yugo:
>>>> give_me_a_car = Car()
>>>> give_me_a_yugo = Yugo()
Объект класса Yugo может реагировать на вызов метода need_a_push():
>>>> give_me_a_yugo.need_a_push()
>A little help here?
А объект общего класса Car — нет:
>>>> give_me_a_car.need_a_push()
>Traceback (most recent call last):
>··File "", line 1, in
>AttributeError: 'Car' object has no attribute 'need_a_push'
К этому моменту класс Yugo может делать что-то, чего не может делать класс Car, и теперь мы точно можем определить отдельную личность класса Yugo.
Просим помощи у предка с помощью ключевого слова super
Мы видели, как класс-потомок может добавить или перегрузить метод класса-предка. Но что, если вам нужно вызвать оригинальный метод родительского класса? «Рад, что вы спросили», — говорит метод super(). Мы определим новый класс, который называется EmailPerson и представляет объект класса Person, содержащий адрес электронной почты. Для начала запишем наше привычное определение класса Person:
>>>> class Person():
>…·····def __init__(self, name):
>…·········self.name = name
>…
Обратите внимание на то, что вызов метода __init__() в следующем подклассе имеет дополнительный параметр email:
>>>> class EmailPerson(Person):
>…·····def __init__(self, name, email):
>…·········super().__init__(name)
>…·········self.email = email
Когда вы определяете метод __init__() для своего класса, вы заменяете метод __init__() родительского класса, который больше не вызывается автоматически. В результате вам нужно вызывать его явно. Происходит следующее.
• Метод super() получает определение родительского класса Person.
• Метод __init__() вызывает метод Person.__init__(). Последний заботится о том, чтобы передать аргумент self суперклассу, поэтому вам нужно лишь передать опциональные аргументы. В нашем случае единственным аргументом класса Person() будет name.
• Строка self.email = email — это новый код, который отличает класс EmailPerson от класса Person.
Теперь создадим одну персону:
>>>> bob = EmailPerson('Bob Frapples', 'bob@frapples.com')
Мы должны иметь доступ к атрибутам name и email:
>>>> bob.name
>'Bob Frapples'
>>>> bob.email
>'bob@frapples.com'
Почему бы нам просто не определить новый класс так, как показано далее?
>>>> class EmailPerson(Person):
>…·····def __init__(self, name, email):
>…·········self.name = name
>…·········self.email = email
Мы могли бы сделать это, но в таком случае потеряли бы возможность применять наследование. Мы использовали метод super(), чтобы создать объект, который работает примерно так же, как и объект класса Person. Есть и другое преимущество: если определение класса Person в будущем изменится, с помощью метода super() мы сможем гарантировать, что атрибуты и методы, которые класс EmailPerson наследует от класса Person, отреагируют на изменения.