首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是不可变集合值对象吗?

是不可变集合值对象吗?
EN

Stack Overflow用户
提问于 2022-10-08 23:47:22
回答 2查看 61关注 0票数 2

根据马丁·福勒其他聪明的人,Value对象是不可变的对象,因为它们的属性的值等于,而不是它们的标识。常见的示例是诸如java.lang.Integer这样的小型“可替换”对象,或者是由组件的相等性定义总体相等的复合对象。

我很好奇,不可变对象的不可变集合(如列表、集合或映射)是否也可以被认为是值对象。例如,如果两个独立的不可变列表对象以相同的顺序包含相同的对象,那么大多数实现都会认为这两个列表是相同的,尽管它们是不同的对象(例如,com.google.common.collect.ImmutableListorg.organicdesign.fp.collections.PersistentHashSet)。这似乎与集合本身是否包含值对象或仅包含常规(非值)不可变对象无关。即使集合包含明显不是值对象的元素(例如闭包或lambdas),两个列表仍然被认为是相等的,尽管它们的组件是通过标识进行比较的。

我的上述推理是否正确,还是存在某些不可变集合(不可变对象)不能被视为值对象?为了明确起见,我从纯OOP、DDD和Design的角度来问这个问题。我知道"Value Object“还有其他含义,例如在ORM上下文中,它可能会影响到存储在数据库中的东西的方式。另外,我的问题假定了一个纯函数背景,其中所有对象都是不可变的。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-10-09 07:06:43

是也不是。

有相当多的重叠,但并不完美。一些不变的集合只是数据结构,而值对象的概念意味着一定程度的显式领域建模。

即使集合包含明显不是值对象的元素(例如闭包或lambdas),两个列表仍然被认为是相等的,尽管它们的组件是通过标识进行比较的。

是也不是。这取决于语言。在Java或C#等语言中,一切都是可比较的。如果您想比较两个函数或lambda,可以在这些语言中这样做,因为所有东西都是一个对象,Object基类定义了一个equals/Equals方法。只有当两个函数实际上指向相同的内存地址时,它们才会被认为是相等的。

哈斯克尔就不是这样了。在这里,与其他任何东西一样,比较两个相等值的能力也是一种抽象。它被称为Eq类型类,但是在这个上下文中,可以将它看作一个接口。只有那些类型是Eq实例(~‘实现那个接口’)可以进行比较。函数和lambda表达式不是Eq实例,因此不能进行比较。这样做的尝试不会编译。

这也适用于列表。在Haskell中,标准(链接)列表是不可变的,具有结构相等,但前提是内容类型是Eq实例。您可以比较两个包含字符串、数字、Money值或User值的列表,只要这些类型是Eq实例。但是您不能比较两个函数列表,因为函数不是Eq实例。

我想说的是,这在更注重面向对象的语言中也是说明性的。结构相等是有用和可取的,但这并不意味着每一个具有结构相等的不变对象都是一个值对象。例如,原始lambda表达式不是。

但是还不清楚,因为有时可以将涉及原始lambda表达式的设计重构为具有“适当”对象的设计。例如,返回布尔值的原始lambda表达式是一个谓词,但您也可以使用Specification对谓词进行建模,在这种情况下,Specification开始看起来像适当的对象。使规范实现不可变,并赋予它们结构相等,它们开始看起来像值对象.

可以使用不可变集合来定义和实现值对象。我可以很容易地想象一个包含Customer对象列表的Address类。如果两个Customer对象具有相同的组成值,包括相同的Address对象列表,那么它们是否相等?是的,我会这么做的。

可变对象的不可变集合是值对象吗?不太可能。

票数 2
EN

Stack Overflow用户

发布于 2022-10-09 21:15:16

从DDD预置来看,如何实现值对象是无关紧要的。正如你所说:

值对象是不可变的对象,它们由于其属性的值而相等,而不是它们的标识。

这个定义中没有任何东西意味着一个特定的实现,实现一个具有不可变集合的值对象只是一个实现细节。

最常见的value对象示例是Money,它可以使用两个属性来实现,一个属性用于值,另一个属性用于货币和地址,其中将地址的不同部分存储在不同的字段中,但所有这些字段一起标识特定的地址。在这些示例中,如果使用某些标识键将它们存储在DB中并不重要,第1行中的“20个USD”将与第100行中的"20美元“相同。

记住这一点,您可以很容易地找到可以用集合实现的值对象的示例。例如,您可以将形状定义为点或坐标的集合,以便用3个点定义一个三角形,而另一个具有相同3个点的集合将完全相同的形状,不考虑它们存储在另一个内存位置或DB中的不同行。因此,在这种情况下,value对象相等将取决于包含相同顺序的相同点的集合。

总之,可以使用不可变集合实现值对象,但定义中并不是所有不可变集合都是值对象。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74001235

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档