Как часто используется принцип Лискова
Что проверяют
Правильный ответ: постоянно, хотя и незаметно. Каждый раз, когда метод принимает List, а вы передаёте ArrayList или неизменяемый список, вы полагаетесь на LSP. Следом обычно просят пример нарушения из самого JDK.
Как отвечать
Определение через контракт: код, написанный под базовый тип, корректно работает с любым подтипом. Для наследника это значит:
- предусловия не усиливать: базовый метод принимает любое число, наследник не может начать отвергать отрицательные;
- постусловия не ослаблять: если база гарантирует непустой результат, наследник тоже;
- инварианты сохранять: и не бросать исключений, которых клиент не ждёт.
Часть правил Java проверяет сама: переопределённый метод не может сузить видимость и объявить более широкие проверяемые исключения, зато может вернуть более узкий тип.
Примеры из JDK:
List.of()иCollections.unmodifiableList(): наaddбросаютUnsupportedOperationException. Javadoc называет такие операции необязательными, но код, который пишет в полученныйList, упадёт;Arrays.asList(): список фиксированного размера,setработает,addиremoveнет;- ковариантность массивов:
Object[] arr = new String[1]; arr[0] = 1;компилируется и падает сArrayStoreException. Обобщения так не умеют, поэтомуList<String>не являетсяList<Object>; Stack extends Vector: наследование ради кода, и стек получил доступ по индексу;java.sql.Timestamp: наследуетjava.util.Date, ноequalsу них несимметричен, и Javadoc прямо просит не считатьTimestampразновидностьюDate.
Где спотыкаются
Путают направление. «Если база ждёт положительные числа, наследник не должен принимать отрицательные» это ошибка: ослаблять предусловие можно, усиливать нельзя.
Сводят принцип к наследованию классов. Интерфейсы и лямбды тоже реализуют контракт: Comparator, нарушающий транзитивность, может уронить Collections.sort с IllegalArgumentException: Comparison method violates its general contract.
Считают, что @Override с throw new UnsupportedOperationException() закрывает вопрос. Это то же нарушение, только отложенное до рантайма.