如果我有一个带有附加属性的新集合,例如:
class NewColl(var name: String, var values: Vector[Int])
extends IndexedSeq[Int] with IndexedSeqLike[Int, NewColl] {...}
如何定义canBuildFrom
和newBuilder
(参见here),以便:if:
var v1 = NewColl("foo",Vector(1,2,3))
var v2 = v1 filter(_ > 1)
var v3 = v1 map(_ + 1)
然后v2.name=="foo"
和v3.name=="foo"
?
答案 0 :(得分:3)
试试这个:
class NewColl(val name: String, val values: Vector[Int])
extends IndexedSeq[Int] with IndexedSeqLike[Int, NewColl] with SeqForwarder[Int] {
override def newBuilder: Builder[Int, NewColl] = NewColl.newBuilder(name)
protected override def underlying = values
}
object NewColl {
def apply(name: String, elems: Vector[Int]) = new NewColl(name, elems)
implicit def canBuildFrom: CanBuildFrom[NewColl, Int, NewColl] = {
new CanBuildFrom[NewColl, Int, NewColl] {
def apply(from: NewColl) = from.newBuilder
def apply() = newBuilder(defaultName)
}
}
private def newBuilder(name: String) = Vector.newBuilder[Int].mapResult(vector => new NewColl(name, vector))
private def defaultName: String = error("no default name")
}
请注意,我已将var
更改为val
,以便与不可变集合保持一致。 SeqForwarder
混合在一起,以避免实现一个方法列表,这些方法都会转发到values
上的相同方法。已在随播对象上实施newBuilder
,并且需要String
参数。
请注意,有时,集合可以在apply()
上免费调用CanBuildFrom
,而无需指定原始集合。在这种情况下,您必须提供默认名称,或者(如此处)抛出异常(仅当您没有设计库并控制新集合的使用时才允许)。