Ответ
L — Принцип подстановки Лисков (Liskov Substitution Principle, LSP).
Формулировка: Объекты базового класса должны быть заменяемы объектами его подклассов без изменения корректности программы. Наследник не должен ужесточать предусловия или ослаблять постусловия, определённые базовым классом.
Пример нарушения LSP в PHP:
interface Document {
public function open(): string;
public function save(): void;
}
class ReadOnlyDocument implements Document {
public function open(): string {
return 'Document content';
}
public function save(): void {
// Нарушение LSP! Подкласс не может выполнить контракт базового класса.
throw new RuntimeException('Save is not allowed for read-only documents');
}
}
function processDocument(Document $doc) {
$content = $doc->open();
// Для ReadOnlyDocument вызовет неожиданное исключение
$doc->save();
}
Исправление через пересмотр иерархии:
interface Document {
public function open(): string;
}
interface WritableDocument extends Document {
public function save(): void;
}
class PdfDocument implements WritableDocument {
public function open(): string { /* ... */ }
public function save(): void { /* ... */ }
}
class ReadOnlyReport implements Document {
public function open(): string { /* ... */ }
// Не реализует save(), что корректно
}
function processDocument(Document $doc) {
$content = $doc->open();
// Теперь функция работает с любым Document
}
function saveDocument(WritableDocument $doc) {
$doc->save(); // Гарантировано безопасно
}
На практике LSP обеспечивает: предсказуемость полиморфного поведения, упрощение модульного тестирования (можно использовать моки базового типа) и предотвращение появления в коде проверок типа if ($obj instanceof SpecificClass).