首页 文章

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

提问于
浏览
5

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

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

var jetSet=Set("Boeing", "Airbus")
jetSet+="Lear"
println(jetSet.contains("Cessna"))

然后声明只有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

但是如果我声明Set为val,则创建不可变集 does not have the += method defined

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"

这里发生了什么?它们都被声明为一个不可变的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)

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

1 回答

  • 13

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

    a += "Colleen"
    

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

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

    a = a + "Colleen"
    

    如果 += 未定义(如不可变的 Set

    显然 +=aval 时没有意义,因为你无法重新分配它,因此被禁止 .

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

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

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

相关问题