我正在尝试在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()方法。我不想指定一种方法来构建它;这应该取决于实施者。这可能吗?
答案 0 :(得分:5)
如果希望map
返回更具体的集合类型,则还应继承TraversableLike
,并将第二个类型参数(表示类型)设置为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
类型的伴随对象。