Всегда ли наследование полиморфно
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Наследование и полиморфизм в Python
Нет, наследование не всегда полиморфно. Это два разных концепта, хотя они часто работают вместе.
Разница между наследованием и полиморфизмом
Наследование — это механизм, при котором дочерний класс получает атрибуты и методы от родительского класса. Это про переиспользование кода.
Полиморфизм — это способность объектов разных классов отвечать на один и тот же вызов метода, но с разной реализацией. Это про интерфейсы и контракты.
Наследование без полиморфизма
Можно наследовать класс, но не переопределять методы (не переживать полиморфизм):
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
print(f"{self.name} издаёт звук")
class Dog(Animal):
pass # Просто наследуем, не переопределяем
dog = Dog("Rex")
dog.speak() # Rex издаёт звук
Здесь Dog наследует speak() от Animal, но не переопределяет его. Полиморфизма нет — просто переиспользование кода.
Полиморфизм через наследование
Полиморфизм появляется, когда дочерний класс переопределяет методы родителя:
class Animal:
def speak(self):
pass # Абстрактный метод
class Dog(Animal):
def speak(self):
return "Гав!"
class Cat(Animal):
def speak(self):
return "Мяу!"
class Bird(Animal):
def speak(self):
return "Чирик!"
def make_animal_speak(animal: Animal):
print(animal.speak()) # Вызов работает для любого Animal
for animal in [Dog(), Cat(), Bird()]:
make_animal_speak(animal) # Каждый животное отвечает по-своему
Здесь полиморфизм позволяет вызывать speak() на объекте типа Animal, не зная точный класс.
Полиморфизм БЕЗ наследования (утиная типизация)
Python поддерживает полиморфизм без наследования — через «утиную типизацию» (duck typing):
class Guitar:
def play(self):
return "Дзинь-дзинь!"
class Piano:
def play(self):
return "Динь-динь!"
class Violin:
def play(self):
return "Писк!"
def perform(instrument):
print(instrument.play()) # Не проверяем тип, просто вызываем play()
for instrument in [Guitar(), Piano(), Violin()]:
perform(instrument) # Работает для любого объекта с методом play()
Здесь нет наследования, но есть полиморфизм! Главное — объект имеет нужный метод.
Абстрактные базовые классы (ABC)
Для явного определения контракта используй абстрактные классы:
from abc import ABC, abstractmethod
class Transport(ABC):
@abstractmethod
def move(self):
pass
class Car(Transport):
def move(self):
return "Машина едет"
class Plane(Transport):
def move(self):
return "Самолёт летит"
# Transport() — ошибка, ABC не может быть instantiated
# Car() и Plane() — работают, реализовали move()
Выводы
- Наследование ≠ полиморфизм. Наследование — способ повторно использовать код
- Полиморфизм нужно реализовывать через переопределение методов
- Python допускает полиморфизм без наследования (duck typing)
- Используй ABC, если хочешь явный контракт и безопасность типов