Перейти к основному содержимому

Наследование и 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 увидят новое значение.