在 PHP 7 中键入属性提示?
php 7 是否支持类属性的类型提示?
我的意思是,不仅仅是为了设置者/获取者,而且对于财产本身。
像这样:
class Foo {
/**
*
* @var Bar
*/
public $bar : Bar;
}
$fooInstance = new Foo();
$fooInstance->bar = new NotBar(); //Error
php 7 是否支持类属性的类型提示?
我的意思是,不仅仅是为了设置者/获取者,而且对于财产本身。
像这样:
class Foo {
/**
*
* @var Bar
*/
public $bar : Bar;
}
$fooInstance = new Foo();
$fooInstance->bar = new NotBar(); //Error
PHP 7.4 将支持类型化属性,如下所示:
class Person
{
public string $name;
public DateTimeImmutable $dateOfBirth;
}
PHP 7.3 及更早版本不支持此功能,但有一些替代方案。
您可以创建一个私有属性,该私有属性只能通过具有类型声明的 getter 和 setter 访问:
class Person
{
private $name;
public function getName(): string {
return $this->name;
}
public function setName(string $newName) {
$this->name = $newName;
}
}
您还可以创建一个公共属性,并使用 docblock 向阅读代码和使用 IDE 的用户提供类型信息,但这不提供运行时类型检查:
class Person
{
/**
* @var string
*/
public $name;
}
事实上,你可以将 getters 和 setters 以及一个 docblock 结合起来。
如果您更喜欢冒险,则可以使用__get,__set
,__isset
和__unset
魔术方法制作假房产,并自己检查类型。不过,我不确定我是否会推荐它。
7.4+:
好消息是,正如@Andrea指出的那样,它将在新版本中实现。我将把这个解决方案留在这里,以防有人想在7.4之前使用它
7.3以下
根据我仍然从这个线程收到的通知,我相信那里的许多人都有/正在遇到与我相同的问题。对于这种情况,我的解决方案是在特征内结合设置器+魔术方法,以模拟这种行为。在这里:__set
trait SettersTrait
{
/**
* @param $name
* @param $value
*/
public function __set($name, $value)
{
$setter = 'set'.$name;
if (method_exists($this, $setter)) {
$this->$setter($value);
} else {
$this->$name = $value;
}
}
}
这是演示:
class Bar {}
class NotBar {}
class Foo
{
use SettersTrait; //It could be implemented within this class but I used it as a trait for more flexibility
/**
*
* @var Bar
*/
private $bar;
/**
* @param Bar $bar
*/
protected function setBar(Bar $bar)
{
//(optional) Protected so it wont be called directly by external 'entities'
$this->bar = $bar;
}
}
$foo = new Foo();
$foo->bar = new NotBar(); //Error
//$foo->bar = new Bar(); //Success
解释
首先,定义为私有属性,以便 PHP 会自动转换。bar
__set
__set
将检查当前对象中是否声明了某个 setter ()。否则,它只会像往常一样设置其值。method_exists($this, $setter)
声明接收类型提示参数 () 的 setter 方法 (setBar)。setBar(Bar $bar)
只要 PHP 检测到不是实例的东西被传递给 setter,它就会自动触发一个致命错误:Uncaught TypeError:传递给 Foo::setBar() 的参数 1 必须是 Bar 的实例,给定 NotBar 的实例Bar