参数化类型的特定生成器 [英] Specific Builder for Parameterized Type

查看:148
本文介绍了参数化类型的特定生成器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在scala中编写一个包装(参数化)集合的类并覆盖它的foreach方法。它对foreach方法的作用对于这个问题的目的并不重要,所以我们可以说它只是在访问时打印每个元素。因此,理想情况下,我们可以使用如下的包装:

  scala> val a = List(1,2,3,4,5)
scala> val b = MyWrapper(a)
scala> b.foreach {x => x}
1
2
3
4
5

关键是我希望这可以与任何迭代器一起工作;不只是一个清单。所以我的第一次尝试就像下面这样:

  class MyWrapper [A,S [A]<:Iterable [A]] (val s:S [A] with IterableLike [A,S [A]])
extends IterableLike [A,S [A]] {

覆盖def foreach [U](f :A => U):Unit = {
iterator.foreach {x =>的println(X); f(x)}
}
}

然而,具体来说,我们需要一个迭代器方法和一个newBuilder方法。迭代器方法没有问题,我们可以像这样窃取它的迭代器:

  override override iterator = s.iterator 

问题是当我尝试定义newBuilder时。我需要建造者返回一个S [A]。但是,S [A]是一个被Iterable [A]限定的参数化集合。因此,所有使用genericBuilder或获取伴随对象的构建器的尝试都会导致Iterable [A]而不是S [A],并带有相应的错误消息

  [error] method newBuilder in trait TraversableLike of type => scala.collection.mutable.Builder [A,S [A]]未定义
[error] method seq in trait Parallelizable of type => scala.collection.TraversableOnce [A]未定义

如何获得构建器的构建器, em> specific type ,S [A],而不是泛型有界类型Iterable [A]?这甚至有可能吗?任何帮助理解惯用的Scala方式来做到这一点(或任何实际工作的方式)将不胜感激! 解决方案

IterableLike (和其他 XxxLike 特性)通过委托给 Builder 对返回类型进行抽象,该特定于每个集合类型。因此,你所尝试的不能工作。



您可以创建一个通用包装器 MyWrapperLike [A,B] 和一些特定的包装器 MySeqWrapper [A]扩展了MyWrapperLike [A,Seq [A]] (与 Set Map List 相同) ),即模仿Scala集合库的设计。


I'm trying to write a class in scala that wraps a (parameterized) collection and overrides it's foreach method. What it does with the foreach method is unimportant for the purpose of this question, so lets say it just prints each element out as it's visited. So ideally, we'd be able to use the wrapper as follows:

scala> val a = List(1,2,3,4,5)
scala> val b = MyWrapper(a)
scala> b.foreach{ x => x }
1
2
3
4
5

The key is that I want this to work with any iterable; not just a list. So my first attempt was something like what follows

class MyWrapper[A, S[A] <: Iterable[A]]( val s: S[A] with IterableLike[A, S[A]]) 
      extends IterableLike[A, S[A]] {

        override def foreach[U](f: A => U): Unit = {
          iterator.foreach{ x => println(x); f(x) }
        }  
 }

However, for this class to be concrete, we need an iterator method and a newBuilder method. The iterator method is no problem, we can just "steal" s's iterator like so:

override def iterator = s.iterator

The problem is when I try to define newBuilder. I need the builder to return an S[A]. However, S[A] is a parameterized collection that is bounded by Iterable[A]. Thus all of my attempts using genericBuilder or getting the companion object's builder result in an Iterable[A] rather than an S[A], with the corresponding error messages

[error] method newBuilder in trait TraversableLike of type => scala.collection.mutable.Builder[A,S[A]] is not defined
[error] method seq in trait Parallelizable of type => scala.collection.TraversableOnce[A] is not defined 

How can I obtain a builder that builds the specific type, S[A], rather than the generic bounded type Iterable[A]? Is this even possible? Any help in understanding the idiomatic Scala way to do this (or any way that actually works) would be greatly appreciated!

解决方案

IterableLike (and the other XxxLike traits) abstract over the return type by delegating to a Builder that has to be specific for each collection type. Hence what you are trying cannot work.

You could create a generic wrapper MyWrapperLike[A, B] and a couple of specific wrappers MySeqWrapper[A] extends MyWrapperLike[A, Seq[A]] (same for Set, Map, List, etc.), i.e. mimic the design of the Scala collection library.

这篇关于参数化类型的特定生成器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆