Ответ
Переопределение метода (method overriding) — это механизм ООП, позволяющий дочернему классу предоставить собственную реализацию метода, который уже определён в родительском классе.
Когда метод вызывается у объекта дочернего класса, исполняется именно его версия, а не версия родительского класса. В Python для этого не нужны специальные ключевые слова — достаточно объявить в дочернем классе метод с тем же именем.
Пример:
class Animal:
def make_sound(self):
print("Издает какой-то звук")
class Dog(Animal):
# Переопределяем метод родительского класса
def make_sound(self):
print("Гав! Гав!")
animal = Animal()
dog = Dog()
animal.make_sound() # Вывод: Издает какой-то звук
dog.make_sound() # Вывод: Гав! Гав!
Расширение, а не замена, с помощью super()
Часто требуется не полностью заменить, а расширить поведение родительского метода. Для вызова реализации из родительского класса используется встроенная функция super().
class Car:
def __init__(self, brand):
self.brand = brand
print(f"Создан автомобиль марки {self.brand}.")
class ElectricCar(Car):
def __init__(self, brand, battery_size):
# Сначала вызываем __init__ родительского класса
super().__init__(brand)
# Затем добавляем свою логику
self.battery_size = battery_size
print(f"Это электромобиль с батареей {self.battery_size} кВт⋅ч.")
my_tesla = ElectricCar("Tesla", 100)
Начиная с Python 3.12, можно использовать декоратор @typing.override для явного указания намерения переопределить метод, что помогает статическим анализаторам находить ошибки.
Ответ 18+ 🔞
Ну вот, смотри, опять эти ваши объектно-ориентированные штуки. Переопределение метода, блядь. Звучит как какая-то бюрократия, а на деле всё просто, как три копейки.
Представь, есть у тебя класс-родитель, типа общего предка. У него есть метод, ну, допустим, make_sound(). Он говорит: "Издает какой-то звук". Ну, типа, неопределёнка, хуйня какая-то.
А теперь появляется его сынок, класс Dog. И этот щенок такой: "Да похуй на твою неопределёнку, отец! Я буду говорить ГАВ!" Вот он и объявляет внутри себя метод с ТАКИМ ЖЕ ИМЕНЕМ — make_sound(), но уже со своей, собачьей реализацией. Это и есть переопределение, ёпта. Когда вызываешь метод у объекта-пёсика, работает уже его версия, а не папина. Родительскую он, блядь, в игнор отправил.
class Animal:
def make_sound(self):
print("Издает какой-то звук")
class Dog(Animal):
# Переопределяем метод родительского класса
def make_sound(self):
print("Гав! Гав!")
animal = Animal()
dog = Dog()
animal.make_sound() # Вывод: Издает какой-то звук
dog.make_sound() # Вывод: Гав! Гав!
Видишь? animal мычит какую-то хуйню, а dog уже конкретно гавкает. Всё, родительский метод накрылся медным тазом для этого экземпляра.
А теперь важный момент, блядь! Часто же не хочется родительский метод полностью выпиливать. Хочется его расширить. Типа: "Папа, твою базовую логику я выполню, но потом ещё и от себя хуйни добавлю". Вот для этого и нужен super() — этакая волшебная палочка, чтобы позвать папину версию метода.
Смотри, вот реальная жизненная ситуация:
class Car:
def __init__(self, brand):
self.brand = brand
print(f"Создан автомобиль марки {self.brand}.")
class ElectricCar(Car):
def __init__(self, brand, battery_size):
# Сначала вызываем __init__ родительского класса
super().__init__(brand) # Эй, пап, инициализируй бренд!
# Затем добавляем свою логику
self.battery_size = battery_size
print(f"Это электромобиль с батареей {self.battery_size} кВт⋅ч.")
my_tesla = ElectricCar("Tesla", 100)
Что здесь происходит? Мы создаём электрокар. Если бы мы просто переопределили __init__ и не вызвали super(), то про бренд все забыли бы нахуй. А так — сначала выполнился папин __init__, который сохранил brand и напечатал первую строчку, а потом уже наш детский код добавил battery_size и вторую строчку. Красота, блядь!
И да, новость для педантов: с Python 3.12 можно использовать декоратор @typing.override. Это такой намёк и компилятору, и тебе самому: "Чувак, я тут намеренно переопределяю метод, если я ебнулся и имя метода опечатал — скажи мне, а то я, бля, сам не замечу!" Удобная штука, чтобы не выстрелить себе в ногу.