在“Scala编程”第三版中,我看到了一个我无法理解的例子。为了理解它,我将它输入到scala解释器中:
scala> import scala.collection.mutable
import scala.collection.mutable
scala> val movieSet = mutable.Set("Hitch", "Poltergeist")
movieSet: scala.collection.mutable.Set[String] = Set(Poltergeist, Hitch)
scala> movieSet
res3: scala.collection.mutable.Set[String] = Set(Poltergeist, Hitch) <<< res3
scala> movieSet += "Shrek"
res4: movieSet.type = Set(Poltergeist, Shrek, Hitch) <<< res4
我的理解是当在一个mutable上做+ =时。该Set应该就地变异(即它所分配的变量不应该改变),但是引用从res3变为res4。 另外,我理解“val movieSet”来创建一个无法更改的值。这不应该导致“val movieSet”保留res3引用,而不是更改为res4吗?
答案 0 :(得分:0)
res3
和res4
只是对同一对象的附加引用,每当您键入具有非单位返回类型但未分配给变量的表达式时,由scala shell生成。当你执行+=
时,该方法会改变集合,并再次返回对同一对象的引用,这样res3
和res4
最终会包含这些内容。
您可以使用eq
方法检查两个值实际上是完全相同的对象(而不是两个相等的对象)。即,res3 eq movieSet
和res4 eq movieSet
都应该是真的。
val
限制变量始终引用同一个对象,但它不会限制该对象以任何方式进行变异。
答案 1 :(得分:0)
mutable.Set#+=
已签名
trait Set[A] {
def +=(elem: A): this.type
}
也就是说,它添加了一个元素,然后返回自己,大概是因为你可以链接像set += "a" += "b"
这样的调用。 REPL为返回生成新val
的事实纯粹是因为它不知道更好。如果你之后输入res3
,你会看到变异。