PassFront
  1. PassFront
  2. База знаний
  3. Принципы S.O.L.I.D

Какие ещё бывают нарушения принципа подстановки Лисков, кроме примера с прямоугольником?

Принципы S.O.L.I.D

LSP ломается не только в геометрии: подтип нарушает контракт, когда требует больше на входе, гарантирует меньше на выходе, бросает неожиданные исключения или меняет побочные эффекты.

Усиление предусловий

PaymentGateway.charge(amount) принимает любую положительную сумму, а CryptoGateway требует amount >= 10. Код, корректный для базы, падает на наследнике.

Ослабление постусловий

Cache.get() обещает вернуть последнее записанное значение, а наследник иногда отдаёт устаревшее. Или sort() в реализации теряет стабильность, на которую опирается вызывающий.

Отказ от операции

class FixedList extends Array {
  push(...items) {
    throw new Error('Список фиксирован');
  }
}

function addDefault(list) {
  list.push('default'); // падает на FixedList
}

Правильнее отдельный тип без мутаций — как ReadonlyArray<T> в TypeScript.

Менее очевидные случаи

  • Новые побочные эффекты: save() в наследнике вдруг отправляет письмо.
  • Нарушение ограничения истории: подтип разрешает менять то, что база считала неизменяемым.
  • Смена сложности: get(i) был O(1), а на связном списке стал O(n) — цикл вызывающего деградирует до O(n²).
  • Вариантность в TS: параметры методов проверяются бивариантно даже со strictFunctionTypes, поэтому компилятор пропустит наследника, сузившего тип аргумента.

Коротко для собеседования

Контракт нарушает подтип, который требует больше, обещает меньше, бросает новые исключения или добавляет побочные эффекты. Такие нарушения ловят контрактными тестами — единым набором тестов базового контракта, прогоняемым на каждой реализации.

Другие вопросы раздела