Наследование и super()
Наследование позволяет создать новый класс на базе существующего: перенять поля и методы родителя и при необходимости изменить или расширить поведение. Это удобно, когда объекты «одного семейства» имеют общую основу, но ведут себя по‑разному.
Базовая идея: «есть‑ли» отношение (is‑a)
Игрок — это общий шаблон. Вратарь — частный случай игрока. Значит, класс Goalkeeper может унаследоваться от HockeyPlayer и переопределить то, что отличается.
class HockeyPlayer:
def __init__(self, name, team):
self.name = name
self.team = team
def role(self):
return 'Игрок'
class Goalkeeper(HockeyPlayer): # наследуемся от HockeyPlayer
def role(self): # переопределяем метод
return 'Вратарь'
g = Goalkeeper('Павел', 'Вымпел')
print(g.name, g.team, g.role())
Павел Вымпел Вратарь
Расширяем конструктор: вызываем super().__init__
В дочернем классе часто нужно добавить новые поля. В этом случае расширяют __init__ и обязательно зовут родительский конструктор через super().
class HockeyPlayer:
def __init__(self, name, team):
self.name = name
self.team = team
class Forward(HockeyPlayer):
def __init__(self, name, team, goals=0):
super().__init__(name, team) # инициализируем часть родителя
self.goals = goals # добавляем поле ребёнка
def score_goal(self):
self.goals += 1
f = Forward('Иван', 'Метеор')
print(f.name, f.team, f.goals)
f.score_goal()
print(f.goals)
Иван Метеор 0
1
Переопределяем, но не ломаем: дополняем поведение через super()
Иногда нужно не заменить метод, а расширить его. Тогда вызываем реализацию родителя и добавляем свою логику.
class HockeyPlayer:
def __init__(self, name, team):
self.name = name
self.team = team
def label(self):
return f"{self.name} — {self.team}"
class Forward(HockeyPlayer):
def label(self):
base = super().label()
return f"{base} (нападающий)"
p = Forward('Иван', 'Метеор')
print(p.label())
Иван — Метеор (нападающий)
Общие данные у наследников: переопределение атрибутов класса
Атрибуты класса унаследуются детьми, но их можно переопределить. Методы класса, обращающиеся к cls, будут видеть значение именно того класса, с которого их вызвали.
class HockeyPlayer:
default_position = 'Игрок'
@classmethod
def get_default_position(cls):
return cls.default_position
class Goalkeeper(HockeyPlayer):
default_position = 'Вратарь'
print(HockeyPlayer.get_default_position())
print(Goalkeeper.get_default_position())
Игрок
Вратарь
Мини‑памятка
- Наследование используем, когда «A — это частный случай B» (отношение is‑a).
- В
__init__дочернего класса всегда вызывайтеsuper().__init__, если родитель что‑то инициализирует. - Переопределяя метод, можно расширить поведение, вызвав реализацию родителя через
super(). - Атрибуты класса наследуются и могут быть переопределены в детях; методы класса через
clsувидят новое значение.