Вот выдержка из этого поста , в которой все проясняется:
[..] Чтобы понять некоторые принципы, важно понимать, когда они были нарушены. Это то, что я буду делать сейчас.
Что означает нарушение этого принципа? Это означает, что объект не выполняет контракт, наложенный абстракцией, выраженной интерфейсом. Другими словами, это означает, что вы неправильно определили свои абстракции.
Рассмотрим следующий пример:
interface Account
{
/**
* Withdraw $money amount from this account.
*
* @param Money $money
* @return mixed
*/
public function withdraw(Money $money);
}
class DefaultAccount implements Account
{
private $balance;
public function withdraw(Money $money)
{
if (!$this->enoughMoney($money)) {
return;
}
$this->balance->subtract($money);
}
}
Это нарушение LSP? Да. Это связано с тем, что договор об аккаунте говорит нам, что аккаунт будет отозван, но это не всегда так. Итак, что я должен сделать, чтобы это исправить? Я просто изменяю договор:
interface Account
{
/**
* Withdraw $money amount from this account if its balance is enough.
* Otherwise do nothing.
*
* @param Money $money
* @return mixed
*/
public function withdraw(Money $money);
}
Вуаля, теперь контракт выполнен.
Это тонкое нарушение часто наделяет клиента способностью различать конкретные используемые объекты. Например, учитывая контракт первого Аккаунта, он может выглядеть следующим образом:
class Client
{
public function go(Account $account, Money $money)
{
if ($account instanceof DefaultAccount && !$account->hasEnoughMoney($money)) {
return;
}
$account->withdraw($money);
}
}
И это автоматически нарушает принцип открытого-закрытого доступа [то есть требования снятия денег. Потому что вы никогда не знаете, что происходит, если у объекта, нарушающего договор, не хватает денег. Возможно, он просто ничего не возвращает, возможно, будет выдано исключение. Таким образом, вы должны проверить, если hasEnoughMoney()
- который не является частью интерфейса. Так что эта принудительная проверка, зависящая от конкретного класса, является нарушением OCP].
Этот пункт также относится к заблуждению, с которым я часто сталкиваюсь по поводу нарушения LSP. В нем говорится «если поведение родителя изменилось у ребенка, значит, оно нарушает LSP». Однако это не так - до тех пор, пока ребенок не нарушает контракт своего родителя.