当声明为var时,Scala不可变集是可变的

Ada*_*ter 6 scala mutable set immutability

我正在阅读Scala编程,第2版(精彩的书,比scala的网站更好,以非摇滚科学的方式解释事物),我注意到这......在回到不可变和可变的时候很奇怪集.

它将以下内容声明为不可变集

var jetSet=Set("Boeing", "Airbus")
jetSet+="Lear"
println(jetSet.contains("Cessna"))
Run Code Online (Sandbox Code Playgroud)

然后声明只有Mutable集定义了+ =方法.好吧,这很有道理.问题是这段代码有效.在REPL中测试时创建的集合类型实际上是不可变集合,但它上面定义了+ =方法,并且它的功能非常好.看哪

scala> var a = Set("Adam", "Bill")
a: scala.collection.immutable.Set[String] = Set(Adam, Bill)

scala> a += "Colleen"

scala> println(a)
Set(Adam, Bill, Colleen)

scala> a.getClass
res8: Class[_ <: scala.collection.immutable.Set[String]] = class scala.collection.immutable.Set$Set3
Run Code Online (Sandbox Code Playgroud)

但是如果我声明Set为val,则创建的Immutable Set 没有定义+ =方法

scala> val b = Set("Adam", "Bill")
b: scala.collection.immutable.Set[String] = Set(Adam, Bill)

scala> b += "Colleen"
<console>:9: error: value += is not a member of scala.collection.immutable.Set[String]
          b += "Colleen"
Run Code Online (Sandbox Code Playgroud)

这里发生了什么?它们都被声明为一个不可变的Set,但声明var可以访问+ =方法并且可以使用它.

另外,当我继续在var Immutable Set上调用getClass方法时,我发现了一些奇怪的东西....

scala> a.getClass
res10: Class[_ <: scala.collection.immutable.Set[String]] = class scala.collection.immutable.Set$Set3

scala> a += "One"

scala> a.getClass
res12: Class[_ <: scala.collection.immutable.Set[String]] = class scala.collection.immutable.Set$Set4

scala> a += "Two"

scala> a.getClass
res14: Class[_ <: scala.collection.immutable.Set[String]] = class scala.collection.immutable.HashSet$HashTrieSet

scala> a += "Tree"

scala> a.getClass
res16: Class[_ <: scala.collection.immutable.Set[String]] = class scala.collection.immutable.HashSet$HashTrieSet

scala> a
res17: scala.collection.immutable.Set[String] = Set(One, Tree, Bill, Adam, Two, Colleen)
Run Code Online (Sandbox Code Playgroud)

我的猜测是,由于一些隐藏的语法糖,Scala认识到它是一个Var并且允许你用新构造的集合替换它.

Gab*_*lla 14

什么是可变的不是Set,是对它的引用.

a += "Colleen"
Run Code Online (Sandbox Code Playgroud)

返回一个新的不可变集,分配给mutable变量 a

Scala执行语法转换,将表达式转换为

a = a + "Colleen"
Run Code Online (Sandbox Code Playgroud)

如果+=没有定义(如在不可变的情况下Set)

显然,+=当没有意义的aval,因为你不能将其重新分配,因此是被禁止的.

以下是Scala编程中的摘录(第17.3节)

为了更容易从不可变集合切换到可变集合,反之亦然,Scala提供了一些语法糖.尽管不可变集和映射不支持真正的+=方法,但Scala提供了一种有用的替代解释+=.无论何时编写a += b,并且a不支持名为的方法+=,Scala都会尝试将其解释为a = a + b

如果您继续阅读该部分,您将通过示例找到更全面的解释.

  • 你还应该提到`+ =`的语法糖翻译,当它没有在类本身上定义时. (3认同)