我正在尝试在Scala 2.8中定义一个自定义集合接口(interface)。我想要求子类具有Traversable,以及其他一些行为。我也希望像map()这样的方法返回适当的类型,如下所示:

trait CustomCollection[+A] extends Traversable[A] {
    def customOperation(i:Int):Int // for example
}

def incrementAll(c:CustomCollection[Int]):CustomCollection[Int] = c.map { _ + 1 }

这不会编译,因为CustomCollection.map()返回一个Traversable。我想我需要定义一个CanBuildFrom,但是随后我需要定义一个apply()方法,该方法从头开始构造一个实例。我不想指定一种构造方法。那应该由实现者来决定。这可能吗?

最佳答案

如果希望map返回更特定的集合类型,则还应该继承TraversableLike,将第二个type参数(表示类型)设置为CustomCollection[A]

接下来,map需要类型为CanBuildFrom的隐式参数。它将在CustomCollection的伴随对象中查找该类型的符合隐式值。如果查看Seq类的源代码,您会发现他们的同伴提供了CanBuildFrom类型的GenericCanBuildFrom对象,该对象将对构建器的调用转发回请求构建器的集合。这样,Seq转换方法的返回类型的动态类型(例如map)总是与序列本身的类型相同。

您要做的是:

  • 使CustomCollection[A]继承TraversableLike
  • 使CustomCollection[A]继承GenericTraversableTemplate
  • 制作CustomCollection的伴随对象并添加一个隐式对象,该对象将返回GenericCanBuildFrom
  • CustomCollection伴侣
  • 中为构建器提供默认实现
    CustomCollection的实现者将需要提供伴随对象,这些对象具有构建器实现和隐式CanBuildFrom对象(可以简单地是GenericCanBuildFrom)。

    编辑:

    需要上面提到的GenericTraversablTemplate,因为它首先确保集合具有genericBuilder构建器工厂调用的GenericCanBuildFrom方法。其次,它确保集合实际上具有GenericCompanion类型的伴随对象。

    10-05 19:07