它会破坏对象的不变性吗?

时间:2018-12-01 10:31:09

标签: php class immutability

我正在阅读:https://www.simonholywell.com/post/2017/03/php-and-immutability/

并举了一个例子,因此它是完美的不可变类:

class Immutable {
    private $skater, $trick;

    public function __construct($skater, $trick) {
        $this->skater = $skater;
        $this->trick = $trick;
    }

    public function getSkater() {
        return $this->skater;
    }

    public function getTrick() {
        return $this->trick;
    }
}
到目前为止,一切都很好。但并非易碎,如文章所述:

$x = new Immutable('Hawk', 'Frontside 540');
$x->__construct('Song', 'Darkslide');

它是这样重写的:

class Immutable {
    private $skater, $trick;
    private $mutable = true;

    public function __construct($skater, $trick) {
        if (false === $this->mutable) {
            throw new \BadMethodCallException('Constructor called twice.');
        }
        $this->skater = $skater;
        $this->trick = $trick;
        $this->mutable = false;
    }

    public function getSkater() {
        return $this->skater;
    }

    public function getTrick() {
        return $this->trick;
    }
}

但是现在更改mute值本身会破坏不变性,对吗? :)

3 个答案:

答案 0 :(得分:2)

不,这不会,因为仅在构造函数中设置了值,此后再也不会更改。因此,它符合不变性的定义。我将User.Identity.GetUserId<int>(). 重命名为$mutable之类的东西,因为您不能真正使用该属性更改类的可变属性,在我看来,它的名称具有误导性。

但是,在某种程度上,PHP完全不可能实现对象不变性,因为:

  

不可移植性并不意味着存储在计算机内存中的对象是不可写的。相反,不变性是一种编译时结构,它指示程序员可以通过对象的常规接口执行的操作,不一定表明他们可以绝对执行的操作

(来源:Wikipedia

由于PHP中没有“编译时”并且$isCreated属性是在运行时评估的,因此从一开始就似乎违反了这一概念。

在另一个级别上,使用相同的引号,“普通界面”将是您的第一个示例所表示的内容。直接而不是通过$mutable调用构造函数方法完全超出了任何常规用法。因此,您可以说没有属性设置器的类通过“通过普通接口”的约定已经不可变。

基本上,您是在询问一个学术问题,但尝试解决一个绝对确定的现实问题,实例化后在任何情况下都不能更改对象的属性。但是“不变性”的概念并不适用。

答案 1 :(得分:1)

两者之间基本没有区别

  private $mutable = true;

然后在构建时将其更改为false,然后:

 private $skater

,然后将其更改为其他内容(在构建时)。当您不设置初始值时,您的意思是:

private $skater = null;

您可以通过在设置值之前执行var_dump($this->skater)来方便地进行检查,它会显示null。因此,实际上,在第一个示例中,您已经将null值更改为其他值。 sandbox那么在构造过程中更改null与更改false之间的区别到底是什么?

无论您是否考虑“不可变”都是一个见解。 PHP中唯一不可变的是常量。

答案 2 :(得分:0)

只要您的不可变类仅接受原始数据类型(例如字符串,int,float,bool),则您的类应该是相当不可变的。但是一旦传递了对象或流,它就不会一成不变。即使有了Value Objects,要获得真正的不可变对象也不容易。