PHP 8.1 中 readonly 有什么好处?

The*_*eky 6 php oop immutability php-8.1

在 PHP 8.1 中,readonly 关键字现已可用。我很好奇它的目的。它是为了帮助编辑者认识到某个属性是只读的,还是为了帮助客户理解这个特性,还是有其他目的?

yiv*_*ivi 11

readonly属性允许您创建不可变的对象,或者至少是不可变的属性。

这样您就可以确保在初始化后的整个对象生命周期中,值不会意外更改。

它与常量(通过const或设置define)的概念非常相似,但有两个重要的区别:

  • 常量需要在“编译”时定义,而readonly属性将在运行时设置,通常是在对象实例化期间(因此多个实例将能够保存不同的值*)
  • 常量存在于全局范围内;对于类常量,它们的值与类相关,而不与实例相关。

可以使用只能通过 getter 访问的私有属性来实现相同的目的。例如,在“过去的日子”:

class Foo {

    private DateTimeImmutable $createAt;

    public function __construct() {
        $this->createdAt = new DateTimeImmutable();
    }

    public function getCreatedAt(): DateTimeImmutable
    {
        return $this->createdAt;
    }
}

$f = new Foo();
echo $f->getCreatedAt()->format('Y-m-d H:i:s');
Run Code Online (Sandbox Code Playgroud)

唯一的问题是它需要大量的样板代码。

使用 PHP 8.1,几乎可以通过执行以下操作来实现相同的效果:

class Foo
{

    public function __construct(
        public readonly DateTimeImmutable $createdAt = new DateTimeImmutable()
    )
    { }

}

$f = new Foo();
echo $f->createdAt->format('Y-m-d H:i:s')
Run Code Online (Sandbox Code Playgroud)

由于 PHP 8.2 添加了readonly类,它变得更好,因为我们可以这样做:

readonly class Foo
{

    public function __construct(
        public string $name,
        public DateTimeImmutable $createdAt = new DateTimeImmutable()
    )
    { }

}
Run Code Online (Sandbox Code Playgroud)

现在 和Foo::name都是Foo::createdAt,readonly和 只能在对象实例化期间设置。