'val'或'var',可变或不可变?

时间:2011-02-22 04:58:49

标签: scala

我可以定义一个不可变的变量(var):

var x = scala.collection.immutable.Set("aaaaaa","bbbbbb")
println(x.isInstanceOf[scala.collection.immutable.Set[String]])
x += "cccc"
println(x.isInstanceOf[scala.collection.immutable.Set[String]])

这导致:

true
true

+=方法不是scala.collection.immutable.Set的成员,那么发生了什么?

2 个答案:

答案 0 :(得分:22)

编译器查找x.+= ...,如果找不到它,则会尝试将语句转换为x = x + ...(仅当x为{{1}时才会成功}},或var desugars调用某些x方法)。由于update实现了immutable.Set运算符,而+x,因此成功。

答案 1 :(得分:6)

原始的不可变集合仍未改变。

继续Ken's answer,+已创建一个新集,附加新项,并返回新集,保持原始集对象不变。所以你可以说var y = x; y += "cccc"而你会有2套而不是1:

var x = scala.collection.immutable.Set("aaaaaa","bbbbbb")
println(x.isInstanceOf[scala.collection.immutable.Set[String]])
var y = x
y += "cccc"
println(x)
println(y)
println(x.isInstanceOf[scala.collection.immutable.Set[String]])
println(y.isInstanceOf[scala.collection.immutable.Set[String]])

获得:

> true
> Set(aaaaaa, bbbbbb)
> Set(aaaaaa, bbbbbb, cccc)
> true
> true

您看到数据结构本身仍然是不可变的,但由于您声明了var,因此赋值是可变的。因此,如果返回它,它可以被重新命名为新对象。如果您更改为将x声明为val,则无法将其重新分配给新地址。

如果您使用了可变集,则xy会指向同一个对象,因为+调用会附加现有集合而不是返回一个新的(可变......):

var x = scala.collection.mutable.Set("aaaaaa","bbbbbb")
println(x.isInstanceOf[scala.collection.immutable.Set[String]])
var y = x
y += "cccc"
println(x)
println(y)

得到:

> Set("aaaaaa","bbbbbb","cccc")
> Set("aaaaaa","bbbbbb","cccc")

瞧。