[英]Is this a valid example of Class invariances using php 7 asserts?
I am trying to understanding a little best the Class Invariances used by Liskov Principle.我试图更好地理解 Liskov 原则使用的类不变性。
I know that some languages like D have native support to invariant , but, using asserts in PHP I've tried combining magic methods and assert:我知道像 D这样的一些语言对 invariant 有本机支持,但是,在 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;
Can I use assert to create a Contract?我可以使用 assert 来创建合约吗?
No不
From PHP Documentation来自PHP 文档
Is BadPerson a valid example to Liskov's Class Invariance violation on inheritance? BadPerson 是 Liskov 在继承上违反类不变性的有效例子吗?
Yes是的
Preconditions cannot be strengthened in a subtype.不能在子类型中加强先决条件。
But your code doesn't make any sense但是你的代码没有任何意义
First your testContract
method will only be invoked if you try to set or get a dynamic property and it will check for the parameters you passed through the constructor
首先,您的testContract
方法只会在您尝试设置或获取动态属性时被调用,并且它将检查您通过constructor
传递的参数
public function __set($name, $value){
$this->testContract();
$this->$name = $value;
}
Here you basically test the constructor parameters but in the magic method ( __set
)在这里,您基本上测试了构造函数参数,但在魔术方法中( __set
)
So in order to make that check works you need to invoke the __set
like this因此,为了使该检查有效,您需要像这样调用__set
$gp = new BadPerson("João", "Joãozinho");
$gp->name = ''; // This line here invokes __set magic method
So what you really need to do is get rid of testContract
and put the check inside the base class constructor.所以你真正需要做的是摆脱testContract
并将检查放在基类构造函数中。 Why?为什么? because your properties are protected
so the only opportunity that clients have for setting them is through the constructor因为您的属性受到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;
}
Is GoodPerson a valid example to Liskov's Classe Invariance? GoodPerson 是 Liskov 的类不变性的有效例子吗?
Yes是的
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.