我有一个函数,它获取一个 Seq[_]
作为参数,并返回一个不可变的类实例,这个 Seq
作为 val 成员。如果 Seq
是可变的,我显然想创建一个防御性副本以保证我的返回类实例不能被修改。
此模式的最佳实践是什么?首先,令我感到惊讶的是不可能重载该函数
def fnc(arg: immutable.Seq[_]) = ...
def fnc(arg: mutable.Seq[_]) = ...
我也可以进行模式匹配:
def fnc(arg: Seq[_]) = arg match {
case s: immutable.Seq[_] => { println("immutable"); s}
case s: mutable.Seq[_] => {println("mutable"); List()++s }
case _: ?
}
但我不确定 _
的情况。是否保证 arg
是 immutable.Seq
或 mutable.Seq
?我也不知道 List()++s
是否是转换它的正确方法。我看到很多关于 SO 的帖子,但其中大部分都是针对 2.8 或更早版本的。
Scala-Collections 是否足够“智能”,以至于我总是可以(无需模式匹配)编写 List()++s
并且如果不可变我得到相同的实例,如果可变我得到深拷贝?
推荐的方法是什么?
最佳答案
如果你想同时支持两者,你将需要模式匹配。 Seq()++
的代码不保证(作为其 API 的一部分)如果它是不可变的,它不会复制其余部分:
scala> val v = Vector(1,2,3)
v: scala.collection.immutable.Vector[Int] = Vector(1, 2, 3)
scala> Seq() ++ v
res1: Seq[Int] = List(1, 2, 3)
对于某些特殊情况,它可能会自行进行模式匹配,但您知道自己想要的情况。所以:
def fnc[A](arg: Seq[A]): Seq[A] = arg match {
case s: collection.immutable.Seq[_] => arg
case _ => Seq[A]() ++ arg
}
你不必担心 _
;这只是说你不关心类型参数到底是什么(不是你可以检查),如果你这样写,你不会:如果不可变则通过,否则复制。
关于scala - 最佳实践 : "If not immutable create copy"-pattern,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14302156/