本文目录导读:

在 PHP 8.2 中引入了只读类(Readonly Classes),这是一个重要的特性,但它也伴随着一系列严格的限制,以下是完整的限制清单:
属性限制
所有属性必须显式声明类型
readonly class User {
public $name; // ❌ 致命错误:必须声明类型
public string $email; // ✅ 正确
}
属性必须是 typed 且不能有默认值
readonly class User {
public string $name = 'John'; // ❌ 致命错误:不能有默认值
public string $email; // ✅ 正确
}
禁止使用 static 属性
readonly class User {
public static string $count = '0'; // ❌ 致命错误:不能有静态属性
}
继承限制
只读类不能被子类继承为普通类
readonly class ParentClass {}
class ChildClass extends ParentClass {} // ❌ 致命错误
非只读类不能继承只读类
class ParentClass {}
readonly class ChildClass extends ParentClass {} // ❌ 致命错误
但只读类可以继承只读类
readonly class ParentClass {}
readonly class ChildClass extends ParentClass {} // ✅ 正确
特质(Trait)限制
只读类不能使用含有非只读属性的 trait
trait HasName {
public string $name = 'John'; // 有默认值
}
readonly class User {
use HasName; // ❌ 致命错误
}
只读类可以使用只读属性的 trait
trait HasEmail {
public string $email; // ✅ 符合只读类要求
}
readonly class User {
use HasEmail; // ✅ 正确
}
属性修饰符限制
不允许使用 var 关键字
readonly class User {
var string $name; // ❌ 致命错误
public string $email; // ✅ 正确
}
不允许使用 static 修饰符
readonly class User {
public static string $count; // ❌ 致命错误
public string $email; // ✅ 正确
}
动态属性限制
禁止动态创建属性
readonly class User {
public string $name;
}
$user = new User();
$user->age = 25; // ❌ 致命错误:不能创建动态属性
序列化限制
不兼容 __wakeup() 和 __unserialize()
readonly class User {
public string $name;
public function __wakeup() {} // ❌ 致命错误
// 或
public function __unserialize(array $data) {} // ❌ 致命错误
}
但 __serialize() 仍然可以
readonly class User {
public string $name;
public function __serialize() { // ✅ 可以(但有警告)
return ['name' => $this->name];
}
}
克隆限制
__clone() 方法不能修改属性
readonly class User {
public string $name;
public function __clone() {
$this->name = 'New Name'; // ❌ 致命错误:不能修改只读属性
}
}
反射限制
ReflectionClass::newInstanceWithoutConstructor() 会创建未初始化状态
$reflection = new ReflectionClass(User::class); $user = $reflection->newInstanceWithoutConstructor(); echo $user->name; // ❌ 错误:未初始化的属性
属性初始化限制
只能在构造函数中初始化(仅一次)
readonly class User {
public string $name;
public function __construct(string $name) {
$this->name = $name; // ✅ 首次初始化
$this->name = 'New'; // ❌ 致命错误:不能再次赋值
}
}
访问级别限制
不允许使用 protected 或 private 属性
readonly class User {
protected string $name; // ❌ 致命错误
private string $email; // ❌ 致命错误
public string $phone; // ✅ 正确,只能是 public
}
只读类的核心设计目的是创建不可变的数据对象,这些限制确保了:
- 类型安全 - 所有属性必须显式声明类型
- 不可变性 - 属性只能在构造函数中初始化一次
- 简化继承 - 防止复杂的继承场景
- 序列化安全 - 防止反序列化时修改只读属性
使用只读类时,需要仔细考虑这些限制,确保设计符合实际需求。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播