【发布时间】:2023-03-30 11:20:01
【问题描述】:
在这个例子中的 php - 但实际上在一般编程中,有没有办法区分 "no-assignment" 和 "unset-value" 命令 @ 987654321@ 合并 2 个相同类型的不可变数据对象时的值?
考虑这个 php 类是一个不可变的数据对象。它在其构造函数中接受一个字符串和一个整数,并且只提供值的访问器:
class Data
{
protected $someNumber;
protected $someString;
public function __construct(?int $someNumber, ?string $someString)
{
$this->someNumber = $someNumber;
$this->someString = $someString;
}
public function getSomeNumber(): ?int
{
return $this->someNumber;
}
public function getSomeString(): ?string
{
return $this->someString;
}
}
这些值始终可以是null 或其各自的数据类型string 或integer。此外,构造函数接受null 值而不是string 和/或int:UNSET 操作。
现在我希望能够合并Data 的2 个实例,类似于接受$first 和$second 的简化工厂方法,其中$second 中的数据会覆盖$first 中的数据(如果存在)。
class DataFactory
{
public function merge(Data $first, Data $second): Data
{
// Uses data from $first if corresponding data from
// $second is (strictly) null
return new Data(
$second->getSomeNumber() ?? $first->getSomeNumber(),
$second->getSomeString() ?? $first->getSomeString(),
}
}
在上面的例子中,$second 的访问器返回的null 值被解释为 NO UPDATE 操作:当遇到null 时,保持$first 的对应值。问题是我希望能够区分merge 中对 NO UPDATE 操作或 UNSET 操作的请求。
Data 类中的严格类型不允许使用诸如"DATA_UNSET_FIELD" 之类的字符串常量作为要标记的值,因此直接在数据本身上实现这一点似乎是不可能的。更重要的是,即使为任何值传递构造函数 null 肯定意味着 SET NULL。
我正在考虑某种更新镜头,它明确指定在合并时应取消设置的属性,以便$second 中的null 值仅意味着没有更新(保留$first)。
解决这个问题的紧凑型面向对象模式是什么?随着数据的增长,我已经可以想象像爆炸普通数组模式或策略类的类爆炸这样的问题。此外,我有点担心Data 对象的“移动性”,因为新对象必须在某些时候与它们相关联。
提前致谢!
编辑
我希望能够区分不覆盖当前值和取消设置一个值——即分配null——当合并@987654347的2个实例时@,其中$first 是基数,$second 覆盖$first 的数据。作为细节,合并会产生第三个新对象,即合并结果。
查看$second中的DataFactorysn-p null值目前被解释为“保留$first的对应值”。但是我如何为每个字段携带另一个标志,指示在结果对象中应该将哪些字段设置为null,以一种干净的方式,并且不会过多地弄乱数据类?
【问题讨论】:
-
在考虑 html 表单时,NO UPDATE“标志”是否类似于“原始”的使用?换句话说(只是为了确保我理解)您想区分未触及的财产和已“摧毁”的财产?
-
@FélixGagnon-Grenier 这并不是我想要做的。我会用更多信息更新我的问题。谢谢!
-
@JeffreyWesterkamp,为什么您需要“能够区分对 NO UPDATE 操作或 UNSET 操作的请求”?你会将这些知识用于什么目的?
-
@sevavietl 在我当前的
merge实现中,如果任一对应的源值不是null,则返回对象的任何属性都没有null值。我的目标是一些扩展的实现,允许我确定是否在返回的对象内显式地将属性设置为 null。这将需要改变当前merge函数的方法——这很好——但我不完全确定最干净/最小的方法。
标签: php oop design-patterns php-7.1