Scala按需生成Set/MutableSet:调用+=方法报错问题
问题原因分析
你的代码报错核心原因有两个:
- 类型被统一为不可变父类型:
mutable.Set[Long]是Set[Long]的子类型,当你用fold合并Either的两个分支时,Scala会将结果类型推断为二者的最小上界Set[Long]。因此无论condition是否为true,GOTTENSET的编译时类型都是不可变的Set[Long],自然无法调用可变集合的+=方法。 fold参数顺序错误:Either.fold的第一个参数是处理Left分支的函数,第二个是处理Right分支的函数,你写反了参数逻辑,不过这个错误因子类型关系被隐藏,没有直接导致编译失败,但逻辑上是错误的。
解决方案
方案1:保留Either类型,使用时显式分支处理
这种方式类型最安全,适合Scala 2和Scala 3:
import scala.collection.mutable val condition: Boolean = true def getSetOrMutableSet(): Either[mutable.Set[Long], Set[Long]] = { if (condition) Left(mutable.Set[Long](11, 11)) else Right(Set.empty[Long]) } lazy val GOTTENSET = getSetOrMutableSet() // 使用时通过模式匹配区分集合类型 GOTTENSET match { case Left(mutableSet) => mutableSet += 14 // 可变集合可直接修改 case Right(immutableSet) => println("无法修改不可变集合") }
方案2:Scala 3使用Union类型简化写法
Scala 3支持Union类型,可以直接将惰性值声明为两种集合类型的联合:
import scala.collection.mutable val condition: Boolean = true lazy val GOTTENSET: Set[Long] | mutable.Set[Long] = if (condition) mutable.Set[Long](11, 11) else Set.empty[Long] // 使用时通过模式匹配操作 GOTTENSET match { case mutableSet: mutable.Set[Long] => mutableSet += 14 case _ => println("不可变集合无法修改") }
方案3:强制类型转换(不推荐,类型不安全)
如果你确定condition为true时一定是可变集合,可以用强制转换绕过编译检查,但这种方式会丢失类型安全:
import scala.collection.mutable val condition: Boolean = true def getSetOrMutableSet(): Either[mutable.Set[Long], Set[Long]] = { if (condition) Left(mutable.Set[Long](11, 11)) else Right(Set.empty[Long]) } lazy val GOTTENSET = getSetOrMutableSet().fold(left => left, right => right) // 仅当condition为true时使用 if (condition) { GOTTENSET.asInstanceOf[mutable.Set[Long]] += 14 }
内容的提问来源于stack exchange,提问作者Friendly Programmer
相关产品推荐
相关产品推荐

