Ответ
Принцип подстановки Барбары Лисков (LSP) является фундаментальным правилом для корректной реализации полиморфизма подтипов. Он утверждает, что объекты производных классов должны быть взаимозаменяемы с объектами базового класса без изменения ожидаемого поведения программы.
Проще говоря, если LSP соблюдается, полиморфный код, работающий с базовым классом, будет корректно работать и с любым его подклассом. Нарушение LSP ведет к необходимости проверок типа (isinstance) и условной логике, что ломает идею полиморфизма.
Пример нарушения LSP
Рассмотрим классический пример с птицами. Если базовый класс Bird имеет метод fly(), то подкласс Penguin нарушит LSP, так как пингвины не летают.
class Bird:
def fly(self):
print("Эта птица летит")
class Duck(Bird):
# Утка - птица, она летает. LSP не нарушен.
def fly(self):
print("Утка летит, крякая")
class Penguin(Bird):
# Пингвин - птица, но он не летает. Нарушение LSP.
def fly(self):
raise NotImplementedError("Пингвины не могут летать!")
# Полиморфная функция
def make_bird_fly(bird: Bird):
try:
bird.fly()
except NotImplementedError as e:
print(f"Ошибка: {e}")
# Использование
duck = Duck()
penguin = Penguin()
make_bird_fly(duck) # Вывод: Утка летит, крякая
make_bird_fly(penguin) # Вывод: Ошибка: Пингвины не могут летать!
Код, ожидающий объект типа Bird, ломается при передаче Penguin. Это прямое следствие нарушения LSP. Правильным решением было бы создание более гранулярной иерархии, например, Bird -> FlyingBird.