泛型 – 参数化类型的特定构建器

我正在尝试在
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]] {

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

但是,要使此类具体,我们需要一个迭代器方法和一个newBuilder方法.迭代器方法没问题,我们可以像这样“窃取”s的迭代器:

override def 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]] is not defined
[error] method seq in trait Parallelizable of type => scala.collection.TraversableOnce[A] is not defined 

如何获得构建特定类型S [A]的构建器,而不是通用的有界类型Iterable [A]?这甚至可能吗?任何有助于理解惯用Scala方式(或任何实际工作方式)的帮助将不胜感激!

最佳答案 IterableLike(以及其他XxxLike特性)通过委托给必须特定于每个集合类型的Builder而在返回类型上进行抽象.因此,你所尝试的是无法奏效的.

你可以创建一个通用的包装器MyWrapperLike [A,B]和一些特定的包装器MySeqWrapper [A]扩展MyWrapperLike [A,Seq [A]](同样适用于Set,Map,List等),即模仿设计Scala集合库.

点赞