Принципы проектирования классов SOLID в PHP
Принцип подстановки Барбары Лисков. (Liskov Substitution Principle, LSP)
Это третий из пяти принципов SOLID и наиболее сложный для понимания.
В оригинале данный принцип звучит так:
Роберт Мартин перефразировал это так:Пусть q(x) является свойством, верным относительно объектов x некоторого типа T.
Тогда q(y) также должно быть верным для объектов y типа S, где S является подтипом типа T.
Иными словами -Функции, которые используют базовый тип, должны иметь возможность использовать подтипы базового типа, не зная об этом.
Поведение наследуемых классов не должно противоречить поведению, заданному базовым классом, то есть поведение наследуемых классов должно быть ожидаемым для кода который использует базовый класс.
Приведем пример
index.php
$bird = new Bird(); $birdRun = new BirdRun($bird); $birdRun->run();
bird.php
/** * Реально используемый в коде класс */ class Bird { public function fly() { $flySpeed = 10; return $flySpeed; } } /** * Дочерний класс от Bird. * Не изменяет поведение, но дополняет. * Не нарушает принцип LSP */ class Duck extends Bird { public function fly() { $flySpeed = 8; return $flySpeed; } public function swim() { $swimSpeed = 2; return $swimSpeed; } } /** * Дочерний класс от Bird. * Изменяет поведение. * Нарушает принцип LSP */ class Penguin extends Bird { public function fly() { //die('i can`t fly ((('); // не типичное поведение - die или exception return 'i can`t fly ((('; // не типичное поведение - возвращаем string, а не integer } public function swim() { $swimSpeed = 4; return $swimSpeed; } }
birdRun.php
class BirdRun { private $bird; public function __construct(Bird $bird) { $this->bird = $bird; } public function run() { $flySpeed = $this->bird->fly(); } }
index.php
$bird = new Bird(); //$bird = new Duck(); //$bird = new Penguin(); $birdRun = new BirdRun($bird); $birdRun->run();
После замены использования Bird на Duck код будет работать как и прежде - принцип LSP соблюден.
После замены Bird на Penguin код меняет свое поведение, следовательно в данном случае принцип LSP нарушен.
Следовать этому типу очень важно при проектировании новых типов с использованием наследования.
Этот принцип предупреждает о том, что изменение унаследованного производным типом поведения очень рискованно.