PHP 怎么PHP 8.2 只读类

wen PHP项目 2

本文目录导读:

PHP 怎么PHP 8.2 只读类

  1. 基本语法
  2. 与普通 readonly 属性的区别
  3. 关键特性
  4. 实际应用示例
  5. 不兼容的 PHP 版本
  6. 最佳实践建议

在 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 及以上版本 可用,在较低版本中会报语法错误。

最佳实践建议

  1. 使用构造函数属性提升 - 结合简写构造函数声明更简洁
  2. 用于不可变对象 - 如 DTO、值对象、配置对象
  3. 不要过度使用 - 只读类不适合需要频繁修改状态的对象
  4. 注意序列化 - 需要特殊处理,因为 __sleep__wakeup 可能不适用

只读类对于建立不可变的数据对象非常有用,可以减少 bug 并使代码更易于理解。

抱歉,评论功能暂时关闭!