Liskov Substitution

Тема дорожной карты · Software Architecture

Принцип подстановки Лисков (Barbara Liskov, 1987) гласит, что подтипы должны быть взаимозаменяемы со своими базовыми типами без изменения корректности программы. Этот принцип является фундаментальным в объектно-ориентированном программировании и играет ключевую роль в обеспечении стабильности и поддерживаемости кода. Нарушение этого принципа может привести к неожиданным багам, которые могут быть труднодоступны для выявления и устранения.

Как это работает

Чтобы обеспечить соблюдение принципа подстановки Лисков, необходимо тщательно проверять, сохраняет ли подтип все предусловия, постусловия и инварианты родителя. Подтип не должен быть более требовательным к входным данным, чем родитель (то есть, не должен требовать больше предусловий). Также подтип не должен обещать меньше, чем родитель (то есть, не должен нарушать постусловия или инварианты). Если хотя бы одно из этих условий нарушено, подтип не является валидной подстановкой по Лисков.

Чтобы исправить нарушение принципа подстановки Лисков, часто используются альтернативные подходы, такие как композиция или создание отдельной иерархии. Эти методы позволяют избежать проблем, связанных с наследованием, и обеспечивают более гибкую и поддерживаемую структуру кода.

Когда применять

Принцип подстановки Лисков особенно важен при создании библиотечного кода, где неизвестные клиенты могут зависеть от контракта родителя. В таких случаях нарушение принципа может привести к серьезным проблемам, поскольку клиенты могут не знать о специфических требованиях или поведении подтипов. Однако, даже в приватном коде приложения, где вы контролируете всех вызывающих функций, соблюдение этого принципа может помочь избежать неожиданных ошибок и упростить поддержку кода.

Типичные ошибки

Существует несколько типичных ошибок, которые могут привести к нарушению принципа подстановки Лисков:

  1. Наследование-по-умолчанию: использование наследования всякий раз, когда формы похожи. Например, можно ошибочно предположить, что квадрат является подтипом прямоугольника, но это не всегда верно с точки зрения поведения. В таких случаях композиция или создание отдельной иерархии может быть более подходящим решением.

  2. Усиление предусловий: подтип требует больше предусловий, чем родитель. Например, если родительский класс принимает любое целое число, а подтип требует только положительные числа, это нарушает принцип подстановки Лисков.

  3. Бросание 'not supported': подтип может выбрасывать исключение "not supported", когда метод поддерживается родителем. Это может быть допустимо с точки зрения языка программирования, но нарушает принцип подстановки Лисков с точки зрения поведения программы.

Связанные понятия

Полезные ресурсы