--- aliases: - LSP - Принцип подстановки Барбары Лисков tags: - maturity/🌱 date: 2024-09-27 --- Принцип подстановки Лисков (Liskov Substitution Principle, LSP) утверждает, что ==объекты подклассов должны быть взаимозаменяемы с объектами базового класса без изменения поведения программы==. Это означает, что ==подклассы не должны нарушать контракт базового класса или изменять его логику==. LSP является третьим принципом в набор[[SOLID|е SOL]]ID и играет ключевую роль в создании устойчивой и понятной иерархии классов. **Чтобы соответствовать LSP:** - Подклассы должны расширять функциональность базового класса, не изменяя его поведение. - [[Контракт взаимодействия|Контракты]], задаваемые базовыми классами, должны строго соблюдаться. - Следует избегать переопределения методов, если это изменяет их ожидаемое поведение. **Преимущества соблюдения LSP:** 1. **Предсказуемость:** Код, использующий базовый класс, будет работать одинаково независимо от того, какие подклассы используются. 2. **Упрощение тестирования:** Система становится менее подверженной ошибкам, так как базовый контракт всегда соблюдается. 3. **Гибкость и масштабируемость:** Добавление новых подклассов не требует модификации существующего кода, если соблюден принцип LSP. 4. **Улучшенная читаемость:** Четкое разделение обязанностей между базовыми и дочерними классами упрощает понимание системы. ## Пример нарушения LSP Рассмотрим иерархию классов для птиц: ```java public class Bird { public void fly() { // Логика полета System.out.println("I can fly!"); } } public class Penguin extends Bird { @Override public void fly() { // Пингвин не может летать — нарушение LSP throw new UnsupportedOperationException("Penguins cannot fly"); } } ``` В данном случае класс `Penguin` нарушает контракт базового класса `Bird`. Код, который ожидает, что любой объект типа `Bird` может летать, перестанет работать корректно при использовании `Penguin`. Это ведет к непредсказуемому поведению программы и увеличивает сложность сопровождения. Для устранения нарушения следует пересмотреть иерархию классов, чтобы явно выделить летающих и нелетающих птиц: ```java public abstract class Bird { // Общие свойства и методы для всех птиц } public interface Flyable { void fly(); } public class FlyingBird extends Bird implements Flyable { @Override public void fly() { // Реализация полета System.out.println("I can fly!"); } } public class Penguin extends Bird { // Пингвин остается нелетающей птицей } ``` Теперь поведение каждой птицы становится очевидным, и программа корректно работает с летающими и нелетающими птицами, не нарушая LSP. *** ## Мета информация **Область**:: [[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]] **Родитель**:: [[SOLID]] **Источник**:: **Создана**:: [[2024-09-27]] **Автор**:: ### Дополнительные материалы - ### Дочерние заметки