如何从泛型方法 return 原始集合类型
How to return the original collection type from generic method
我有一个通用方法,它应该 return 一个与输入相同类型的集合:
def removeN[A, C <: Seq[A]](s: C, n: Int): C = {
s.take(n) ++ s.drop(n + 1) // Sample operation
}
但是这段代码无法编译:
Error:(34, 15) type mismatch; found : Seq[A] required: C
s.take(n) ++ s.drop(n + 1)
- 当
C
明明代表 Seq[A]
时,这怎么可能?这是否意味着这种连接总是 return 父类型 Seq[A]
的实例,而不是子类型 C
的实例?可以重写我的代码以生成 C
类型的集合吗?
- 这是定义通用方法的正确方法吗?return与一般输入具有相同的集合类型(在我的例子中是
Seq
的子类型)?
Scala 2.12.4
您所要求的可以使用集合库中最强大但最有争议的功能之一来完成,即 CanBuildFrom
。方法如下:
import scala.language.higherKinds
import scala.collection.generic.CanBuildFrom
def removeN[A, C[A] <: Seq[A]](s: C[A], n: Int)
(implicit cbf: CanBuildFrom[C[A], A, C[A]]): C[A] = {
val builder = cbf()
builder.sizeHint(s.size)
builder ++= s.take(n)
builder ++= s.drop(n + 1)
builder.result()
}
让我们在 REPL 中稍微改变一下:
scala> removeN(List(4, 5, 6), 2)
res0: List[Int] = List(4, 5)
scala> removeN(Vector(4, 5, 6), 2)
res1: scala.collection.immutable.Vector[Int] = Vector(4, 5)
这似乎有效。
需要 import scala.language.higherKinds
以避免对高级 (C[A]) 用法发出警告。
我有一个通用方法,它应该 return 一个与输入相同类型的集合:
def removeN[A, C <: Seq[A]](s: C, n: Int): C = {
s.take(n) ++ s.drop(n + 1) // Sample operation
}
但是这段代码无法编译:
Error:(34, 15) type mismatch; found : Seq[A] required: C s.take(n) ++ s.drop(n + 1)
- 当
C
明明代表Seq[A]
时,这怎么可能?这是否意味着这种连接总是 return 父类型Seq[A]
的实例,而不是子类型C
的实例?可以重写我的代码以生成C
类型的集合吗? - 这是定义通用方法的正确方法吗?return与一般输入具有相同的集合类型(在我的例子中是
Seq
的子类型)?
Scala 2.12.4
您所要求的可以使用集合库中最强大但最有争议的功能之一来完成,即 CanBuildFrom
。方法如下:
import scala.language.higherKinds
import scala.collection.generic.CanBuildFrom
def removeN[A, C[A] <: Seq[A]](s: C[A], n: Int)
(implicit cbf: CanBuildFrom[C[A], A, C[A]]): C[A] = {
val builder = cbf()
builder.sizeHint(s.size)
builder ++= s.take(n)
builder ++= s.drop(n + 1)
builder.result()
}
让我们在 REPL 中稍微改变一下:
scala> removeN(List(4, 5, 6), 2)
res0: List[Int] = List(4, 5)
scala> removeN(Vector(4, 5, 6), 2)
res1: scala.collection.immutable.Vector[Int] = Vector(4, 5)
这似乎有效。
需要import scala.language.higherKinds
以避免对高级 (C[A]) 用法发出警告。