Приведите пример нарушения принципа подстановки Барбары Лисков (LSP) в стандартных библиотеках Java.

«Приведите пример нарушения принципа подстановки Барбары Лисков (LSP) в стандартных библиотеках Java.» — вопрос из категории ООП, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Принцип подстановки Лисков (LSP): Объекты базового класса должны быть заменяемы объектами производного класса без изменения корректности программы.

Классическое нарушение в Java: Класс java.util.Stack<E>, который наследуется от java.util.Vector<E>.

Почему это нарушение LSP? Stack по своей семантике — структура данных LIFO (Last-In-First-Out). Его публичный контракт — операции push, pop, peek. Наследуясь от Vector, он «наследует» множество публичных методов, которые нарушают этот контракт и позволяют модифицировать стек произвольным образом.

import java.util.Stack;

public class LSPViolationExample {
    public static void main(String[] args) {
        Stack<String> stack = new Stack<>();
        stack.push("First"); // Корректная операция стека
        stack.push("Second");

        // НАРУШЕНИЕ LSP: Методы, унаследованные от Vector,
        // ломают инварианты стека (доступ к произвольному элементу).
        stack.insertElementAt("Intruder", 0); // Метод из Vector!
        stack.remove(1);                      // Метод из Vector!

        // Теперь поведение pop() не соответствует LIFO.
        System.out.println(stack.pop()); // Что будет выведено? Неочевидно.
    }
}

Следствия нарушения:

  • Ненадежность: Клиентский код, использующий Stack как Vector, может сломать логику стека.
  • Нарушение инкапсуляции: Внутреннее состояние (порядок элементов) можно изменить в обход основных методов.
  • Невозможность безопасной замены: Stack не может быть использован везде, где ожидается Vector, без риска ошибок.

Правильная реализация (соответствующая LSP) должна была использовать композицию: хранить Vector или ArrayList как приватное поле и предоставлять только методы стека, делегируя им вызовы к внутренней коллекции.