Введение

Принцип объектно-ориентированного программирования

Принцип подстановки Лискова (LSP) — это конкретное определение отношения подтипов, называемое строгим поведенческим подтипированием, которое было впервые представлено Барбарой Лисковой в 1987 году в ключевом докладе на конференции под названием «Абстракция данных и иерархия». Он основан на концепции «заместимости» — принципе объектно-ориентированного программирования, утверждающем, что объект (например, класс) может быть заменен на подобъект (например, класс, наследующий от первого класса) без нарушения работы программы. Это семантическое, а не только синтаксическое отношение, поскольку оно призвано гарантировать семантическую совместимость типов в иерархии, особенно типов объектов. Барбара Лискова и Джанетт Уинг кратко описали этот принцип в статье 1994 года следующим образом:

Требование к подтипу: пусть φ(x) — свойство, доказуемое для объектов x типа T. Тогда φ(y) должно быть истинным для объектов y типа S, где S является подтипом T.

Символически:

То есть, если S является подтипом T, то всё, что верно для объектов T, верно и для объектов S. В той же статье Лискова и Уинг подробно описали свое понимание поведенческого подтипирования в расширении логики Хоара, которое имеет некоторое сходство с подходом «Разработка на основе контрактов» Бертранда Мейера, поскольку рассматривает взаимодействие подтипирования с предусловиями, постусловиями и инвариантами.

Принцип

Понятие Лискова о поведенческом подтипе определяет понятие заменяемости объектов; то есть, если S является подтипом T, то объекты типа T в программе могут быть заменены объектами типа S без изменения каких-либо желаемых свойств этой программы (например, корректности). Поведенческое подтипирование — более сильное понятие, чем типичное подтипирование функций, определенное в теории типов, которое основывается только на контравариантности типов параметров и ковариантности типа возвращаемого значения. Поведенческое подтипирование в общем случае неразрешимо: если q — это свойство "метод для x всегда завершается", то для программы (например, компилятора) невозможно проверить, что оно верно для некоторого подтипа S типа T, даже если q действительно верно для T. Тем не менее, принцип полезен при рассуждениях о разработке иерархий классов. Принцип подстановки Лискова налагает некоторые стандартные требования к сигнатурам, которые были приняты в новых объектно-ориентированных языках программирования (обычно на уровне классов, а не типов; см. номинальное и структурное подтипирование для различия):

* Контравариантность типов параметров метода в подтипе.
* Ковариантность типов возвращаемых значений метода в подтипе.
* Новые исключения не могут выбрасываться методами в подтипе, за исключением случаев, когда они являются подтипами исключений, выбрасываемых методами супертипа.

Помимо требований к сигнатуре, подтип должен соответствовать ряду поведенческих условий. Они подробно описаны в терминологии, напоминающей методологию "проектирование по контракту", что приводит к некоторым ограничениям во взаимодействии контрактов с наследованием:

* Предусловия не могут быть усилены в подтипе.
* Постусловия не могут быть ослаблены в подтипе.
* Инвариант не может быть ослаблен в подтипе.
* Историческое ограничение ("правило истории").

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

Происхождение

Правила предусловий и постусловий идентичны тем, что были введены Бертраном Мейером в его книге 1988 года «Объектно-ориентированное построение программного обеспечения». И Мейер, и позже Пьер Америка, который первым использовал термин «поведенческое подтипирование», дали теоретико-доказательные определения некоторых понятий поведенческого подтипирования, но их определения не учитывали алиасинг, который может возникать в языках программирования, поддерживающих ссылки или указатели. Учет алиасинга стал основным улучшением, внесенным Лисков и Вингом (1994), а ограничение истории является ключевым элементом. Согласно определениям Мейера и Америки, изменяемая точка была бы поведенческим подтипом неизменяемой точки, в то время как принцип подстановки Лисков это запрещает.

Конкретные ссылки

Основной доклад, в котором Лисков впервые сформулировал этот принцип.

Общие сведения

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