我想从现有的Seq集合中创建一个新的自定义Scala集合。我有一个名为Ref的特征,其中包含如下数据
trait Ref[A] {
def get: A
def getAsOption: Option[A]
def dataType: Class[A]
// other methods
}
我的自定义集合名为Vec,它是Ref [A]的序列(即Vec [A]等同于Seq [Ref [A]]),我想创建这样的自定义集合的原因是因为我想保留Ref in collection的类型参数,用于在自定义方法中处理。我的代码如下
trait VecLike[A, +Repr <: Seq[Ref[A]]]
extends SeqLike[Ref[A], Repr]
with TraversableLike[Ref[A], Repr] {
// custom methods
}
trait GenVec[A]
extends VecLike[A, Seq[Ref[A]]]
with Seq[Ref[A]]
with PartialFunction[Int, Ref[A]]
abstract class AbstractVec[A](vec: Ref[A]*)
extends AbstractSeq[Ref[A]]
with GenVec[A] {...}
class Vec(vec: Ref[A]*)
extends AbstractVec[A](vec:_*)
with VecLike[A, Vec[A]]
with GenericTraversableTemplate[Ref[A], Seq]
但是当我调用map()函数
时Vec(1,2,3,4).map(intToString)
返回Seq [String],预期结果为Vec [String]。我还尝试使用SeqFactory [Seq]在伴随对象中创建自定义CanBuildFrom但它失败了。 :( :(
有人可以就此提出一些建议,以及我如何实现这一目标吗?
答案 0 :(得分:3)
您需要在Builder
中实现自定义newBuilder
并使VecLike
方法返回。
查看此页面,获取有关实施自定义集合的非常好的教程:http://docs.scala-lang.org/overviews/core/architecture-of-scala-collections.html
答案 1 :(得分:0)
我完成了,这是我的错误,我创建了错误的CanBuildFrom。以下是CanBuildFrom的完整实现(CBF灵感来自Scala GenericCanBuildFrom)
trait VecLike[A, +Repr]
extends SeqLike[Ref[A], Repr]
trait GenVec[A]
extends AnyRef
with VecLike[A, GenVec[A]]
trait Vec[A]
extends GenVec[A]
with VecLike[A, Vec[A]]
abstract class AbstractVec[A](vec: Seq[Ref[A]])
extends AnyRef
with Vec[A]
final class VecImpl[A](vec: Seq[Ref[A]])
extends AbstractVec[A](vec)
object Vec {
private[this] val VecCBFInstance: VecCanBuildFrom[Nothing] = new VecCanBuildFrom[Nothing] {
override def apply() = newBuilder[Nothing]
}
private def VecCBF: VecCanBuildFrom[Nothing] = VecCBFInstance
private class VecCanBuildFrom[A] extends CanBuildFrom[Vec[_], A, Vec[A]] {
def apply(from: Vec[_]) = newBuilder[A]
def apply() = newBuilder[A]
}
implicit def canBuildFrom[A]: CanBuildFrom[Vec[_], A, Vec[A]] = VecCBF.asInstanceOf[VecCanBuildFrom[A]]
}
现在我可以在调用map()函数后接收Vec结果而不是Seq,如下所示
val vec = Vec(1,2,3,4)
var vecStr : Vec[String] = vec.map(intToString)