本文目录导读:

在 PHP 8.2 中,引入了 只读类(Readonly Classes) 的特性,这意味着你可以将一个类标记为 readonly,从而该类中的所有属性都会被隐式地设置为 readonly,简化了只读数据对象的创建。
基本语法
<?php
readonly class User {
public string $name;
public int $age;
public function __construct(string $name, int $age) {
$this->name = $name;
$this->age = $age;
}
}
// 使用
$user = new User('Alice', 30);
echo $user->name; // 输出: Alice
// 尝试修改属性会报错
// $user->name = 'Bob'; // Fatal error: Cannot modify readonly property
与普通 readonly 属性的区别
在 PHP 8.1 中,你可以单独声明只读属性:
class Product {
public readonly string $sku;
public string $name;
}
而 PHP 8.2 的只读类是更高级的语法糖,等价于将类中的所有属性都声明为 readonly。
关键特性
所有属性自动成为只读
readonly class Point {
// 不需要每个属性都写 readonly
public float $x;
public float $y;
public float $z;
// 构造函数中初始化
public function __construct(float $x, float $y, float $z = 0.0) {
$this->x = $x;
$this->y = $y;
$this->z = $z;
}
}
不允许声明静态属性
只读类不能包含静态属性:
readonly class Config {
// Fatal error: Readonly class Config cannot contain static properties
// public static string $appName = 'MyApp';
}
不允许声明动态属性
readonly class Demo {
public string $name;
public function __construct(string $name) {
$this->name = $name;
}
}
$demo = new Demo('Test');
// $demo->extra = 'value'; // Error: Cannot create dynamic property
类型声明是强制的
每个属性都必须有类型声明:
readonly class Item {
// Fatal error: Readonly property Item::$name must have type
// public $name;
public string $name; // 正确
}
支持继承
readonly class Base {
public string $baseProp;
}
// 不强制子类也是 readonly
class Child extends Base {
public string $childProp;
}
// 子类也可以是 readonly
readonly class ReadonlyChild extends Base {
public string $childProp;
}
可以定义方法和接口
interface Jsonable {
public function toJson(): string;
}
readonly class User implements Jsonable {
public function __construct(
public string $name,
public int $age
) {}
public function toJson(): string {
return json_encode([
'name' => $this->name,
'age' => $this->age
]);
}
}
实际应用示例
数据传输对象(DTO)
readonly class CreateUserRequest {
public function __construct(
public string $username,
public string $email,
public ?string $phone = null
) {}
}
// 使用
$request = new CreateUserRequest('john_doe', 'john@example.com');
echo $request->email; // john@example.com
配置对象
readonly class DatabaseConfig {
public function __construct(
public string $host,
public int $port,
public string $database,
public string $username,
public string $password
) {}
}
// 使用构造函数参数提升
$config = new DatabaseConfig(
host: 'localhost',
port: 3306,
database: 'myapp',
username: 'root',
password: 'secret'
);
值对象
readonly class Money {
public function __construct(
public float $amount,
public string $currency
) {
if ($amount < 0) {
throw new \InvalidArgumentException('Amount cannot be negative');
}
}
}
$price = new Money(99.99, 'USD');
不兼容的 PHP 版本
只读类仅在 PHP 8.2 及以上版本 可用,在较低版本中会报语法错误。
最佳实践建议
- 使用构造函数属性提升 - 结合简写构造函数声明更简洁
- 用于不可变对象 - 如 DTO、值对象、配置对象
- 不要过度使用 - 只读类不适合需要频繁修改状态的对象
- 注意序列化 - 需要特殊处理,因为
__sleep和__wakeup可能不适用
只读类对于建立不可变的数据对象非常有用,可以减少 bug 并使代码更易于理解。
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播