PHP 中的不可变对象?

2022-08-30 21:41:11

创建无法在PHP中更改的对象是一个好主意吗?

例如,具有 setter 方法的日期对象,但它们将始终返回该对象的新实例(带有修改日期)。

这些对象是否会让使用该类的其他人感到困惑,因为在PHP中,您通常期望对象发生变化?

$obj = new Object(2);

$x = $obj->add(5); // 7
$y = $obj->add(2); // 4

答案 1

不可变对象没有 setter 方法。时期。

每个人都会期望一个方法具有 void 返回类型(或者在松散类型的语言中不返回任何内容)。如果你确实将 setter 方法添加到你的不可变对象中,它会混淆人们的地狱,并导致丑陋的错误。setXyz()


答案 2

在我看来,对象对于值对象应该是不可变的。除此之外,除非您在整个应用程序中共享对象,否则它没有太大的好处。

这里有一些错误的答案,一个不可变的对象可以有 setter。以下是PHP中不可变对象的一些实现。

示例 #1.

class ImmutableValueObject
{
    private $val1;
    private $val2;

    public function __construct($val1, $val2)
    {
        $this->val1 = $val1;
        $this->val2 = $val2;
    }

    public function getVal1()
    {
        return $this->val1;
    }

    public function getVal2()
    {
        return $this->val2;
    }
}

如您所见,一旦实例化,您就无法更改任何值。

示例 2:使用 :setters

class ImmutableValueObject
{
    private $val1;
    private $val2;

    public function __construct($val1, $val2)
    {
        $this->val1 = $val1;
        $this->val2 = $val2;
    }

    public function getVal1()
    {
        return $this->val1;
    }

    public function withVal1($val1)
    {
        $copy = clone $this;
        $copy->val1 = $val1;

        return $copy;    // here's the trick: you return a new instance!
    }

    public function getVal2()
    {
        return $this->val2;
    }

    public function withVal2($val2)
    {
        $copy = clone $this;
        $copy->val2 = $val2;

        return $copy;
    }
}

有几种可能的实现,这绝不是一个排他性列表。请记住,使用Reflectle,总有一种方法可以在PHP中解决这个问题,所以不可变性最终都在你的脑海中!

将不可变对象作为最终对象通常也是一种很好的做法。

编辑:

  • 为 withX 更改了 setX
  • 添加了有关最终的评论

推荐