Принцип подстановки Лискова – это L в ТВЕРДЫХ принципах. Он был создан Барбарой Лисков и заявляет:
Подтипы должны иметь возможность заменять базовые типы.
Помимо очевидной реализации этого принципа – обеспечения того, чтобы подтип имел то же поведение, что и базовый тип, – неявная реализация гарантирует, что подтип имеет то же семантическое поведение, что и базовый тип.
Семантика определяется как:
Относящийся к значению в языке или логике.
Итак, мы создаем определение того, что означает имя класса. Как правило, квадраты и прямоугольники определяются с помощью их математического определения. Математически квадрат – это фигура с четырьмя сторонами равной длины. Для прямоугольников мы будем использовать определение идеального прямоугольника, что означает форму, в которой верхняя и нижняя стороны имеют одинаковую длину, а левая и правая стороны имеют одинаковую длину.
Из этого определения мы можем сделать вывод, что ширина и высота квадрата должны быть одинаковыми, в то время как прямоугольник может иметь ширину, отличную от его высоты, а также ширину, равную его высоте.
Давайте создадим классы для этих фигур, где мы просто определим ширину и высоту.
Мы можем видеть, что Квадратный
объект может легко заменить объект Прямоугольник
в данной ситуации. Все объекты Square
ведут себя так же, как и объекты Rectangle
.
Однако мы можем увидеть семантическую разницу, когда тестируем #area()
.
Поскольку высота прямоугольника может отличаться от его ширины, результат #area()
соответствует нашему семантическому определению.
Если бы мы заменили Прямоугольник
с Квадрат
тест пройдет, но объект Квадрат
больше не ведет себя так, как мы ожидаем.
Поскольку ширина и высота квадрата не могут быть разными, объект Square
нарушает наше семантическое определение. Это нарушает принцип подстановки Лискова.
Самый простой способ обеспечить оба прямоугольника
и Квадрат
пройти тест, удовлетворяя LSP, состоит в том, чтобы удалить строку 4.
Возможно, вы думаете, почему бы не реализовать функцию #setWidth()
в Прямоугольник
, который может быть перезаписан в Площадь
? Это привело бы к Square
для совместного использования только интерфейса Прямоугольник
вместо его поведения, что делает абстракцию ненужной. Удалив строку 4, мы можем удовлетворить LSP, и мы можем пойти еще дальше, сделав width
и высота
частная.
в заключение
При реализации наследования обязательно придерживайтесь значения класса вне реализации. Это помогает классу стать более понятным в общей схеме проекта.
Другой метод, который помогает обеспечить соответствие классов LSP, – это design by contract .
Оригинал: “https://dev.to/naomidennis/a-light-introduction-liskov-substitution-principle-295a”