php - 为什么 PHP 在 unset() 声明类型属性后调用 __set()?
问题描述
(编辑了这个问题,旧版本引用了RFC的错误版本。)
PHP 中类型化属性的RFC说“如果类型化属性是unset()
,那么它将返回到未初始化状态。” 但是,在 PHP 7.4(至少到 7.4.5)中,当类实现时__set()
,它的行为确实有所不同,因此它与(原始)未初始化状态不完全相同。第一次设置未初始化的属性时不会调用魔术函数,但在取消设置后再次设置属性时会(意外地)调用它。示例代码。
<?php
class X {
public int $y;
public function __set($name, $value) {
echo "__set($name, $value) called";
$this->$name = $value;
}
}
$x = new X();
$x->y = 42; // Prints nothing, as expected.
unset($x->y);
$x->y = 43; // Prints `__set(y, 43) called`.
我忽略了什么吗?这是 PHP 当前如何unset()
为类型化属性实现的错误吗?或者__set()
甚至应该在第一次设置未初始化的类型属性时调用?
解决方案
为什么?
出于惰性初始化模式的目的。
如果一个类型化的属性是 unset(),那么它返回到未初始化的状态。虽然我们很乐意删除对取消设置属性的支持,但此功能目前被 Doctrine 用于延迟初始化
因此,在 PHP 8 中,他们可能会在为延迟初始化提供一些替代机制之后禁止取消设置已声明的属性。
推荐阅读
- url-shortener - 为什么常见的 url 缩短器使用随机字符串而不是随机单词组合
- eslint - 使用自动转换的 tslint 到 eslint 转换错误
- lua - lua_pushstring 随机 bitflip 损坏
- php - Laravel 请求 - 检索数据
- python-3.x - 如何将 rawdate 转换为“YYYY-MM-DD HH:MM:SS”
- bash - 使用 DigitalOcean 液滴结束 ssh 会话时如何保留退出代码?
- excel - 将表中的数据提取到数组中,然后重新打印到新工作表上
- ruby-on-rails - ActiveRecord 根据表 B 中的对应列更新表 A 中的列
- python - Volttron 上的 Python3 支持
- java - 我的概率/机会系统有什么错误?