dav*_*000 10 scala immutability
考虑这个简化的应用领域:
Person 是参与调查的任何人Report 是调查的一部分信息Report引用主要Person(调查的主题)Report具有次要相关的共犯(并且在其他调查或报告中肯定是主要的如果这些存储在某种数据库中并且我希望使用不可变对象,则似乎存在关于状态和引用的问题.
假设我改变了一些关于a的元数据Person.由于我的Person对象是不可变的,我可能会有一些代码:
class Person(
val id:UUID,
val aliases:List[String],
val reports:List[Report]) {
def addAlias(name:String) = new Person(id,name :: aliases,reports)
}
Run Code Online (Sandbox Code Playgroud)
因此,我Person的新别名成为一个新对象,也是不可变的.如果a Report指的是那个人,但别名在系统的其他地方被改变了,我Report现在指的是"老"人,即没有新别名的人.
同样,我可能会:
class Report(val id:UUID, val content:String) {
/** Adding more info to our report */
def updateContent(newContent:String) = new Report(id,newContent)
}
Run Code Online (Sandbox Code Playgroud)
由于这些对象不知道是谁引用它们,因此我不清楚如何让所有"引用者"知道有一个新对象可用来代表最近的状态.
这可以通过让所有对象从中央数据存储"刷新"并且创建新的,更新的对象的所有操作存储到中央数据存储来完成,但这感觉就像是对基础语言的引用的简洁重新实现.也就是说,让这些"次要可存储物体"变得可变更为明确.因此,如果我向a添加别名Person,则所有引用者都会看到新值而不执行任何操作.
当我们想要避免可变性时,如何解决这个问题,或者这是不可变性无效的情况?
Rex*_*err 10
如果X指向Y,两者都是不可变的,并且Y更改(即用更新的副本替换它),那么你别无选择,只能替换X(因为它已经改变,因为新的X指向新的Y,不是旧的).
在高度互联的数据结构中维护这种情况很快就会成为头疼 你有三种一般方法.
我希望,哪个更好取决于您的查找和更新速度.
我建议你阅读他们如何处理clojure和Akka中的问题.阅读有关软件事务内存的信息.还有一些我的想法......
不变性不是为了它本身而存在的.不变性是抽象的.它本质上不"存在".世界是可变的,世界永远在变化.因此,数据结构可变是很自然的 - 它们描述了在给定时刻的真实或模拟对象的状态.它看起来像OOP rulez.在概念层面,这种态度的问题是RAM中的对象!=真实对象 - 数据可能不准确,它带有延迟等
因此,在最琐碎的要求的情况下,你可以使用一切可变的 - 人,报告等实际问题将出现在:
使用天真的可变模型,您很快就会得到不一致的数据和破碎系统.可变性容易出错,不可变性是不可能的.你需要的是世界的交易视图.在交易程序中看到不可变的世界.STM管理以一致且线程安全的方式应用的更改.
| 归档时间: |
|
| 查看次数: |
755 次 |
| 最近记录: |