Scala中的val-mutable与var-immutable

Jam*_*abe 94 collections functional-programming scala immutability

Scala中是否有关于何时使用可变集合的val与使用带有不可变集合的var的指南?或者你真的应该用不可变的集合来瞄准val吗?

事实上,这两种类型的集合给了我很多选择,而且我常常不知道如何做出这种选择.

Dan*_*ral 100

很常见的问题,这一个.困难的是找到重复的东西.

你应该争取参考透明度.这意味着,如果我有一个表达"e",我可以制作一个val x = e,并替换ex.这是可变性破坏的属性.无论何时您需要做出设计决策,最大限度地提高参考透明度.

实际上,方法本地var是最安全的var,因为它不会逃避该方法.如果方法很短,甚至更好.如果不是,请尝试通过提取其他方法来减少它.

另一方面,可变集合有可能逃脱,即使它没有.更改代码时,您可能希望将其传递给其他方法,或将其返回.这就是打破参考透明度的那种东西.

在一个物体(一个场地)上,几乎发生了同样的事情,但会产生更多可怕的后果.无论哪种方式,对象都将具有状态,因此会破坏参照透明度.但是拥有一个可变的集合意味着即使对象本身也可能无法控制谁在改变它.

  • 在我的脑海中,很好的,全新的大图:在`mutable var`上更喜欢'immutable var`而不是`mutable val`.特别是`不可变的var`超过`mutable val`! (38认同)
  • 请记住,您仍然可以通过本地可变`var`关闭(如泄漏可以改变它的副作用"功能").使用不可变集合的另一个好处是,即使`var`发生变异,您也可以有效地保留旧副本. (2认同)

Mal*_*off 17

如果您使用不可变集合并且需要"修改"它们,例如,在循环中向它们添加元素,那么您必须使用vars,因为您需要将结果集合存储在某处.如果只读取不可变集合,则使用vals.

通常,请确保不要混淆引用和对象.vals是不可变引用(C中的常量指针).也就是说,当你使用val x = new MutableFoo(),你就可以更改的对象x指向,但你不能切换到一个对象 x点.如果您使用,则相反var x = new ImmutableFoo().提出我的初步建议:如果你不需要更改参考指向的对象,请使用vals.

  • @JimPivarski我和其他人一样不同意,请看Daniel的回答和Peter的评论.如果您需要更新数据结构,那么使用不可变var而不是可变val具有以下优点:您可以泄漏对结构的引用,而不会冒被其他人修改的方式,从而破坏您的本地假设.这些"他人"的缺点是,他们可能会读取过时的数据. (3认同)

jma*_*zin 9

回答这个问题的最佳方法是举个例子.假设我们有一些过程只是出于某种原因收集数字.我们希望记录这些数字,并将集合发送到另一个进程来执行此操作.

当然,我们在将集合发送到记录器后仍在收集数字.并且假设在日志记录过程中存在一些延迟实际日志记录的开销.希望你能看到它的发展方向.

如果我们将这个集合存储在一个mutable中val,(可变,因为我们不断添加它),这意味着执行日志记录的进程将查看仍由我们的集合进程更新的同一对象.该集合可以随时更新,因此当需要记录时,我们可能实际上并未记录我们发送的集合.

如果我们使用不可变var,我们将不可变数据结构发送到记录器.当我们向集合中添加更多数字时,我们将使用新的不可变数据结构替换我们的数字.这并不意味着发送到记录器的集合已被替换!它仍然引用它发送的集合.所以我们的记录器确实会记录它收到的集合.var