我正在尝试在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
类型的伴随对象。