【发布时间】:2021-08-04 17:47:37
【问题描述】:
首先,我是英文新手,如有错误请见谅
DateTime 和 DateTimeImmutable 2 个类实现了相同的接口 DateTimeInterface。因此我想知道:
-
这 2 个类 DateTime 和 DateTimeImmutable 有什么区别?
-
这些类的用例是什么?
【问题讨论】:
首先,我是英文新手,如有错误请见谅
DateTime 和 DateTimeImmutable 2 个类实现了相同的接口 DateTimeInterface。因此我想知道:
这 2 个类 DateTime 和 DateTimeImmutable 有什么区别?
这些类的用例是什么?
【问题讨论】:
不同之处在于“不可变”部分,这意味着一旦创建了对象,它就永远不会改变(wiki for more info)。这意味着每当您修改 DateTime 时,相同的实例将被更改,但当您修改 DateTimeImmutable 时,将返回一个新的修改实例。
一般来说,不可变对象在创建后永远不会改变它的状态。相反,当需要修改时,它将返回具有修改状态的同一类的新实例。
它们都实现相同的DateTimeInterface 的事实有点令人困惑,但可以通过接口没有描述DateTime 和DateTimeImmutable 提供的所有可用功能这一事实来解释。更准确地说,接口不包含允许状态更改的方法。
选择其中一个的用例主要取决于偏好、编码标准,在某种程度上,还取决于对代码质量的需求与对开发速度的需求。
【讨论】:
区别的核心在DateTime类的documentation中有描述:
该类的行为与 DateTimeImmutable 相同,只是对象在调用 DateTime::modify() 等修改方法时会自行修改。
让我们通过一个具体的例子来观察这种差异:
$date = new DateTime();
$tomorrow = $date->modify('+1 day');
echo $date->format('Y-m-d');
echo $tomorrow->format('Y-m-d');
这将输出:
2021-05-15
2021-05-15
这里发生的事情是 modify 返回了 DateTime 对象的相同实例。变量$tomorrow 不包含不同的对象,它包含对原始对象的引用。更新新变量也修改了原来的变量。
如果我们执行相同的修改,但在不可变版本上:
$date = new DateTimeImmutable();
$tomorrow = $date->modify('+1 day');
echo $date->format('Y-m-d');
echo $tomorrow->format('Y-m-d');
这将输出:
2021-05-14
2021-05-15
因为在DateTimeImmutable 中,修改方法不会返回相同的实例,它们会为您提供一个新实例(也是不可变的)。这也意味着您必须将其结果分配给不可变版本的变量(如前面的示例)才能使用它:
$date = new DateTime('2021-05-14');
$date->modify('+1 day');
echo $date->format('Y-m-d'); // 2021-05-15
$date = new DateTimeImmutable('2021-05-14');
$date->modify('+1 day');
echo $date->format('Y-m-d'); // 2021-05-14; original is untouched
由于这种行为,不可变版本几乎总是比可变版本更受欢迎。不小心修改了您不想修改的日期实例是一个很常见的错误。
您可能更喜欢可变版本以避免在您可以可靠地确定不存在损害应用程序状态的危险的情况下执行分配步骤,但最好在您牢牢掌握概念。
除了modify,以下方法也被认为是变异的:
addsubsetDatesetISODatesetTimesetTimezone【讨论】:
Immutable->modify() 返回一个新的不可变 对象。因此,新对象上的每个后续modify() 也必须分配给一个变量。我花了一段时间才知道。