使用新属性扩展scala集合

时间:2011-07-10 11:37:13

标签: scala scala-collections

如果我有一个带有附加属性的新集合,例如:

class NewColl(var name: String, var values: Vector[Int])
    extends IndexedSeq[Int] with IndexedSeqLike[Int, NewColl] {...} 

如何定义canBuildFromnewBuilder(参见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"

1 个答案:

答案 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,而无需指定原始集合。在这种情况下,您必须提供默认名称,或者(如此处)抛出异常(仅当您没有设计库并控制新集合的使用时才允许)。

另见that question