使用新属性扩展 scala 集合

发布于 2024-11-19 05:12:25 字数 546 浏览 2 评论 0原文

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

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

如何定义 canBuildFromnewBuilder (参见 此处)这样,如果:

var v1 = NewColl("foo",Vector(1,2,3))
var v2 = v1 filter(_ > 1)
var v3 = v1 map(_ + 1)

v2.name=="foo"v3.name==“foo”

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 v3 = v1 map(_ + 1)

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

山人契 2024-11-26 05:12:25

试试这个:

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 参数。

请注意,有时,集合可以自由地在 CanBuildFrom 上调用 apply(),而无需指定原始集合。在这种情况下,您要么必须提供默认名称,要么(像这里一样)抛出异常(仅当您不设计库并控制新集合的使用时才允许)。

另请参阅该问题

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文