Php 它是否破坏了对象的不变性?
我在读这篇文章: 并且遇到了一个例子,所以它是完美的不可变类:Php 它是否破坏了对象的不变性?,php,class,immutability,Php,Class,Immutability,我在读这篇文章: 并且遇到了一个例子,所以它是完美的不可变类: class Immutable { private $skater, $trick; public function __construct($skater, $trick) { $this->skater = $skater; $this->trick = $trick; } public function getSkater() {
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
值本身会破坏不变性,对吗?:) 否,它不会,因为该值仅在构造函数中设置,以后从未更改。所以它符合不变性的定义。我会将$mutable
重命名为$isCreated
或其他名称,因为您无法使用此属性更改类的可变属性,我认为它的命名有误导性
但是,在某种程度上,PHP中的对象不变性根本不可能实现,因为:
不变性并不意味着存储在计算机内存中的对象是不可写的。相反,不变性是一种编译时构造,它指示程序员可以通过对象的正常接口做什么,而不一定是绝对可以做什么
(来源:)
由于PHP中没有“编译时”,并且$mutable
属性是在运行时计算的,因此它似乎从一开始就违反了这个概念
在另一个层面上,使用相同的引语,“普通接口”将是您的第一个示例所代表的。直接调用构造函数方法而不是通过new
调用构造函数方法完全超出了正常使用范围。因此,您可以说,根据“通过普通接口”的约定,属性没有设置器的类已经是不可变的
基本上,您是在问一个学术问题,但试图解决一个现实世界的问题,即绝对确定对象的属性在实例化后在任何情况下都不能更改。但是“不变性”的概念并不适用。不,它不适用,因为该值仅在构造函数中设置,以后从未更改。所以它符合不变性的定义。我会将
$mutable
重命名为$isCreated
或其他名称,因为您无法使用此属性更改类的可变属性,我认为它的命名有误导性
但是,在某种程度上,PHP中的对象不变性根本不可能实现,因为:
不变性并不意味着存储在计算机内存中的对象是不可写的。相反,不变性是一种编译时构造,它指示程序员可以通过对象的正常接口做什么,而不一定是绝对可以做什么
(来源:)
由于PHP中没有“编译时”,并且$mutable
属性是在运行时计算的,因此它似乎从一开始就违反了这个概念
在另一个层面上,使用相同的引语,“普通接口”将是您的第一个示例所代表的。直接调用构造函数方法而不是通过new
调用构造函数方法完全超出了正常使用范围。因此,您可以说,根据“通过普通接口”的约定,属性没有设置器的类已经是不可变的
基本上,您是在问一个学术问题,但试图解决一个现实世界的问题,即绝对确定对象的属性在实例化后在任何情况下都不能更改。但是“不变性”的概念并不适用。只要您的不可变类只接受基本数据类型(如string、int、float、bool),您的类就应该是相当不可变的。但一旦你传递了对象或流,它就不是一成不变的。即使使用值对象,也不容易获得真正的不可变对象。只要不可变类只接受基本数据类型(如字符串、int、float、bool),那么类应该是相当不可变的。但一旦你传递了对象或流,它就不是一成不变的。即使使用值对象,也不容易获得真正的不可变对象。以下两者之间没有根本区别:
private $mutable = true;
然后(在施工时)将其更改为false
,然后:
private $skater
然后在以后(施工时)将其更改为其他内容。当您不设置初始值时,您所说的是:
private $skater = null;
在设置值之前,您可以通过执行var\u dump($this->skater)
来轻松检查这一点,它将显示null
。因此,在第一个示例中,实际上您已经在将null值更改为其他值。那么,在构造时更改null
和更改false
之间到底有什么区别呢
你是否认为不可改变是一种看法。PHP中唯一不变的是常量。以下两者之间没有根本区别:
private $mutable = true;
然后(在施工时)将其更改为false
,然后:
private $skater
然后在以后(施工时)将其更改为其他内容。当您不设置初始值时,您所说的是:
private $skater = null;
在设置值之前,您可以通过执行var\u dump($this->skater)
来轻松检查这一点,它将显示null
。因此,在第一个示例中,实际上您已经在将null值更改为其他值。那么,在构造时更改null
和更改false
之间到底有什么区别呢
你是否认为不可改变是一种看法。PHP中唯一不可变的是常量。这是我今年听到的最奇怪的事情<代码>等级纬度(浮动$lat);类经度(浮动$lon);类点(纬度$lat,经度$lon);上课时间(整数$unixTime);类位置(点$位置,时间$时间)代码>。只要对象的方法不改变对象的状态,它就是不可变的。我想知道你所说的“获得一个真正的不可变对象并不容易”是什么意思。@emix你知道引用是如何工作的吗?什么是“不想要的副作用”吗?这是我今年听到的最奇怪的事情<代码>等级纬度(浮动$la