Применяется ли принцип подстановки Лискова к классам, реализующим интерфейс?

17

LSP утверждает, что классы должны быть заменяемыми для их базовых классов, а это означает, что производные и базовые классы должны быть семантически эквивалентными.

Но применяется ли LSP к классам, реализующим интерфейс? Другими словами, если метод интерфейса, реализуемый классом, семантически отличается от того, что пользователь ожидает от него, будет ли это рассматриваться как нарушение LSP?

user1483278
источник
7
Да. Точно такие же причины и результаты, как нарушение LSP, если это интерфейс, абстрактный класс, полный класс, не имеет значения. LSP - это установление и удовлетворение ожиданий, чтобы потребители могли относиться к вашим типам в целом.
Джимми Хоффа
5
В целом (я знаю различия, но я обобщаю здесь), интерфейсы в некоторой степени аналогичны чисто абстрактным классам (термин C ++), и поэтому Лисков должен применяться к интерфейсам и классам, которые их реализуют.
Джесси С. Slicer
3
NB формулировка LSP, с которой я знаком, говорит о подтипах, а не о производных и базовых классах. Я полагаю, что на то есть веская причина, потому что ни одна из причин не является специфичной для наследования и применима так же, как и к любому другому типу подтипов.

Ответы:

17

если интерфейсный метод, реализованный классом, семантически отличается от того, что пользователь ожидает от него, будет ли это рассматриваться как нарушение LSP?

Если реализация семантически отличается от поведения, задокументированного через инварианты интерфейса и предварительные и постусловия его методов, тогда ответ «да», это будет нарушением LSP. Принцип устанавливает правила для абстракции и ее реализации, не требуя, чтобы сторона абстракции присутствовала в форме класса.

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

dasblinkenlight
источник
«Если реализация семантически отличается от поведения, задокументированного через инварианты интерфейса», не могли бы вы пояснить, что вы подразумеваете под «инвариантами интерфейса»?
user1483278
3
@ user1483278 Вот статья об инвариантах типов . В статье они называются «инвариантами классов», но описание относится и к интерфейсам. Инварианты - это условия, которые устанавливаются при построении и поддерживаются в течение всего жизненного цикла экземпляра. Например, если у интерфейса есть свойство, Nameкоторое нельзя установить равным null, то obj.Name != nullговорят, что он является инвариантом этого интерфейса.
dasblinkenlight
1
Обычно, когда обсуждаются инварианты, можно написать кусок кода, чтобы убедиться, что инвариант поддерживается в течение всего времени жизни объекта. Тем не менее, как правило, более просто описать инвариант на простом английском языке.
Rwong