💡 SOLID: принцип подстановки Лисков (LSP) говорит: 🔁 объекты базового класса должны без проблем заменяться объектами его подклассов.
🔁 объекты базового класса должны без проблем заменяться объектами его подклассов.
Если подкласс меняет поведение так, что код начинает ломаться — дизайн неправильный.
❌ Плохой пример
У нас есть Vehicle с методом startEngine().
Мы наследуем Bicycle, но… у велосипеда нет двигателя — и метод бросает исключение.
Такая иерархия:
class Vehicle {
public void startEngine() { ... }
}
class Bicycle extends Vehicle {
@Override
public void startEngine() {
throw new UnsupportedOperationException("Bicycles don't have engines!");
}
}
Теперь любой тест, ожидающий, что любой Vehicle умеет завести двигатель, падает.
👉 Подкласс ведёт себя не так, как базовый — LSP нарушен.
✅ Как исправить
Разделяем ответственность на интерфейсы:
interface Vehicle {}
interface Motorized {
void startEngine();
}
class Car implements Vehicle, Motorized {
public void startEngine() { ... }
}
class Bicycle implements Vehicle {
// без двигателя — всё ок
}
Теперь только те объекты, которым по смыслу нужен двигатель, реализуют Motorized.
🧠 Вывод
✔️ Подклассы не должны ломать ожидания, заложенные в базовый класс.
✔️ Лучше разделить поведение, чем «затыкать» методы исключениями.
✔️ LSP делает код предсказуемым и безопасным для расширения.