Является ли это допустимым примером инвариантности классов с использованием утверждений php 7?
Я пытаюсь лучше понять инвариантность классов, используемую принципом Лискова.
Я знаю, что некоторые языки, такие как D, имеют встроенную поддержку инварианта, но, используя утверждения в PHP, я пробовал комбинировать магические методы и утверждать:
<?php
class Person {
protected string $name;
protected string $nickName;
protected function testContract(){
assert(($this->name != $this->nickName));
}
public function __construct(string $name, string $nickName){
$this->name = $name;
$this->nickName = $nickName;
}
public function __set($name, $value){
$this->testContract();
$this->$name = $value;
}
public function __get($name){
$this->testContract();
return $this->$name;
}
}
class GoodPerson extends Person {
public function getFullName(){
return $this->name." ".$this->nickName. "!!!";
}
}
class BadPerson extends Person {
protected function testContract(){
assert(($this->name != ""));
}
}
$gp = new GoodPerson("João", "Joãozinho");
echo $gp->nickName;
echo $gp->getFullName();
$bp = new BadPerson("João", "João");
echo $bp->nickName;
- Могу ли я использовать assert для создания контракта?
- Является ли BadPerson допустимым примером нарушения инвариантности классов Лискова при наследовании?
- Является ли GoodPerson действительным примером классовой инвариантности Лискова?
1 ответ
Могу ли я использовать assert для создания контракта?
Нет
- Утверждения следует использовать только как функцию отладки
- Утверждения не должны использоваться для обычных операций времени выполнения, таких как проверка входных параметров.
Является ли BadPerson допустимым примером нарушения инвариантности классов Лискова при наследовании?
да
Предпосылки нельзя усилить в подтипе.
Но ваш код не имеет смысла
Сначала твой testContract
будет вызываться только в том случае, если вы попытаетесь установить или получить динамическое свойство, и он проверит параметры, которые вы передали через constructor
public function __set($name, $value){
$this->testContract();
$this->$name = $value;
}
Здесь вы в основном тестируете параметры конструктора, но в магическом методе (__set
)
Итак, чтобы эта проверка работала, вам нужно вызвать __set
нравится
$gp = new BadPerson("João", "Joãozinho");
$gp->name = ''; // This line here invokes __set magic method
Итак, что вам действительно нужно сделать, так это избавиться от testContract
и поставьте галочку внутри конструктора базового класса. Почему? потому что ваша недвижимостьprotected
поэтому единственная возможность, которая есть у клиентов для их настройки, - через конструктор
public function __construct(string $name, string $nickName){
if ($name != "" && $name != $nickName)
throw new Exception('Name must not be empty and must not equal Nickname');
$this->name = $name;
$this->nickName = $nickName;
}
Является ли GoodPerson действительным примером классовой инвариантности Лискова?
да