【问题标题】:'val' or 'var', mutable or immutable?'val' 或 'var',可变还是不可变?
【发布时间】:2011-07-01 17:52:01
【问题描述】:

我可以定义一个不可变的变量(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 的成员,这是怎么回事?

【问题讨论】:

  • 请注意,x 现在拥有一个 new 集合。如果您接受其他以相同方式工作的收集方法,我认为这种行为非常直观和有意。
  • val x = 试试会给你答案的线索

标签: scala


【解决方案1】:

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

【讨论】:

  • 很高兴知道我一直很聪明,总是避免使用 +=/*=/... 快捷方式。
  • 我今天才发现map(key) += value 可以在可变地图上工作。我现在会进入程序员的地狱吗?
【解决方案2】:

原来的不可变集仍然没有改变。

继续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,则无法将其重新分配给新地址。

如果您使用了 mutable 集,那么 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")

瞧。

【讨论】:

    猜你喜欢
    • 2012-07-08
    • 1970-01-01
    • 2018-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-29
    • 2010-11-20
    • 2020-10-14
    相关资源
    最近更新 更多