Принцип подстановки Барбары Лисков (Liskov Substitution Principle, LSP)

Принцип подстановки Барбары Лисков (Liskov Substitution Principle, LSP) – это один из пяти принципов SOLID, который формулируется следующим образом: объекты подклассов должны быть способны заменить объекты базовых классов без изменения желательных свойств программы. Этот принцип определен Барбарой Лисков и утверждает, что подклассы должны следовать тем же контрактам (интерфейсам) и предоставлять те же функциональные возможности, что и их родительские классы.

Ключевые концепции LSP:

  1. Совместимость с базовым классом: Если у нас есть класс и его подкласс, то подкласс должен быть способен использоваться везде, где используется базовый класс, без изменения логики программы.
  2. Подклассы могут дополнять поведение, но не изменять его: Подклассы могут добавлять новые методы и свойства, а также расширять функциональность базового класса, но они не должны изменять или нарушать предполагаемое поведение базового класса.
  3. Обеспечение инвариантов: Инварианты, определенные для базового класса, должны быть сохранены и в подклассах. Инварианты – это условия или ограничения, которые должны соблюдаться во всех состояниях объекта.

Пример нарушения LSP:

python

class Bird: def fly(self): pass class Ostrich(Bird): def fly(self): # Острич не умеют летать, поэтому метод fly переопределен, но не выполняет никаких действий pass

В этом примере, хотя класс Ostrich является подклассом Bird, он нарушает принцип LSP, так как переопределяет метод fly и не выполняет действия, хотя ожидается, что все подклассы Bird будут способны летать.

Пример, соблюдающий LSP:

python

class Bird: def move(self): pass class Sparrow(Bird): def move(self): print("Сквозь воздух") class Penguin(Bird): def move(self): print("Плавая в воде") class Ostrich(Bird): def move(self): print("Бегом по земле")

В этом примере каждый подкласс Sparrow, Penguin и Ostrich соблюдает контракт базового класса Bird, реализуя метод move, который предоставляет разное поведение для каждого типа птицы. Это соблюдение принципа LSP, так как каждый подкласс можно использовать вместо базового класса Bird без изменения логики программы.