如何在不定义实现的情况下在Scala中定义自定义集合接口?

时间:2011-01-07 15:00:40

标签: scala scala-2.8 scala-collections

我正在尝试在Scala 2.8中定义自定义集合界面。我想要求子类是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()方法。我不想指定一种方法来构建它;这应该取决于实施者。这可能吗?

1 个答案:

答案 0 :(得分:5)

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

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

你要做的是:

  1. CustomCollection[A]继承TraversableLike
  2. CustomCollection[A]继承GenericTraversableTemplate
  3. 制作CustomCollection的伴随对象,并添加隐含的返回GenericCanBuildFrom
  4. CustomCollection随播广告
  5. 中为构建商提供默认实施

    CustomCollection的实现者需要提供具有构建器实现和隐式CanBuildFrom对象的伴随对象(可以简单地为GenericCanBuildFrom)。

    编辑:

    上面提到的

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