开发者

extending scala collections with new attribute

If I have a new collection with an additional attribute, e.g. :

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

how do I define canBuildFrom and newBuilder (cf. here) such that if:

var v1 = NewColl("foo",Vector(1,2,3))
var v2 = v1 filter(_ > 1)
var开发者_Python百科 v3 = v1 map(_ + 1)

then v2.name=="foo" and v3.name=="foo"?


Try this:

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")
}

Note that I've changed your vars into vals here to be consistent with an immutable collection. SeqForwarder has been mixed in to avoid implementing a list of methods that would all forward to the same method on values. newBuilder has been implemented on the companion object and needs a String parameter.

Note that sometimes, collections are free to call apply() on the CanBuildFrom without specifying the originating collection. In that case, you either have to provide a default name, or (like here) throw an exception (permissible only if you're not designing a library and control the use of your new collection).

See also that question.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜