Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Що означає принцип підстановки Лісков і як його порушують на практиці?

LSP («L» у SOLID): об'єкт підтипу має бути можливо підставити скрізь, де очікується базовий тип, без зміни правильності програми. Нащадок має виконувати контракт предка, а не лише мати ті самі методи.

Класичне порушення - квадрат і прямокутник:

class Rectangle
{
    public function setWidth(int $w): void { $this->width = $w; }
    public function setHeight(int $h): void { $this->height = $h; }
    public function area(): int { return $this->width * $this->height; }
}

class Square extends Rectangle
{
    public function setWidth(int $w): void { $this->width = $this->height = $w; }
    public function setHeight(int $h): void { $this->width = $this->height = $h; }
}

function stretch(Rectangle $r): void
{
    $r->setWidth(5);
    $r->setHeight(2);
    assert($r->area() === 10);   // для Square - 4
}

Математично квадрат - прямокутник, але поведінково ні: незалежна зміна сторін - частина контракту Rectangle.

Як порушують у реальному коді:

  • Метод нащадка кидає NotImplementedException чи нічого не робить: ReadOnlyRepository extends Repository з save(), що кидає виняток.
  • Посилені вимоги до вхідних даних: предок приймає будь-який рядок, нащадок - лише непорожній.
  • Послаблені гарантії результату: предок завжди повертає об'єкт, нащадок - інколи null.
  • Нові винятки, яких клієнти базового типу не очікують і не ловлять.
  • Перевірка типу в коді клієнта: if ($shape instanceof Square) - ознака, що підстановка не працює.

Що робити: якщо нащадок не може виконати контракт, він не має бути нащадком. Розділити інтерфейси (ReadableRepository, WritableRepository - принцип розділення інтерфейсів), використати композицію або незмінні об'єкти (незмінний квадрат цілком може бути незмінним прямокутником).

PHP частково допомагає: перевизначений метод не може звузити типи параметрів чи розширити тип повернення (контраваріантність і коваріантність перевіряються). Але поведінковий контракт рушій не перевіряє - лише тести й увага.

Докладніше в документації: Liskov substitution principle

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання