如何在 Scala 中定义自定义集合接口而不定义实现?
我正在尝试在 Scala 2.8 中定义自定义集合接口。我想要求子类是可遍历的,以及一些其他行为。我还希望像 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() 方法来从头开始构造一个实例。我不想指定一种构建方法;这应该由实施者决定。这可能吗?
I'm trying to define a custom collection interface in Scala 2.8. I want to require that subclasses be Traversable, plus some other behavior. I also want methods like map() to return the appropriate type, as below:
trait CustomCollection[+A] extends Traversable[A] {
def customOperation(i:Int):Int // for example
}
def incrementAll(c:CustomCollection[Int]):CustomCollection[Int] = c.map { _ + 1 }
This doesn't compile, because CustomCollection.map() returns a Traversable. I suppose I need to define a CanBuildFrom, but then I need to define an apply() method that constructs an instance from scratch. I don't want to specify a way to construct this; that should be up to the implementer. Is this possible?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果您希望
map
返回更具体的集合类型,那么您还应该继承TraversableLike
,并将第二个类型参数(表示类型)设置为CustomCollection[A ]
。接下来,
map
需要一个CanBuildFrom
类型的隐式参数。它将在CustomCollection
的伴生对象中查找以查找该类型的一致隐式值。如果您查看Seq
类的源代码,您会发现它们的同伴提供GenericCanBuildFrom
类型的CanBuildFrom
对象,用于转发调用对于构建器返回请求构建器的集合。这样,Seq
转换器方法(例如map
)的返回类型的动态类型始终与序列本身的类型相同。你需要做的是:
CustomCollection[A]
继承TraversableLike
CustomCollection[A]
继承GenericTraversableTemplate
CustomCollection
的伴生对象,并添加一个返回GenericCanBuildFrom
的隐式对象CustomCollection
伴生中的构建器提供默认实现的实现者>CustomCollection
将需要提供具有构建器实现和隐式CanBuildFrom
对象(可以简单地是GenericCanBuildFrom
)的伴随对象。编辑:
上面提到的
GenericTraversablTemplate
是必需的,因为它首先确保集合将具有由GenericCanBuildFrom
构建器工厂调用的genericBuilder
方法。其次,它确保集合实际上具有GenericCompanion
类型的伴生对象。If you want
map
to return a more specific collection type, then you should also inheritTraversableLike
, with the second type parameter (representation type) set toCustomCollection[A]
.Next,
map
requires an implicit parameter of typeCanBuildFrom
. It will look in the companion object ofCustomCollection
to find a conforming implicit value of that type. If you take a look at the source code ofSeq
classes, you will see that their companions provideCanBuildFrom
objects of typeGenericCanBuildFrom
which forwards the call for the builder back to the collection that requested the builder. That way, the dynamic type of return type ofSeq
transformer methods (e.g.map
) is always the same as the type of the sequence itself.What you have to do is:
CustomCollection[A]
inheritTraversableLike
CustomCollection[A]
inheritGenericTraversableTemplate
CustomCollection
and add an implicit which returns aGenericCanBuildFrom
CustomCollection
companionThe implementers of
CustomCollection
will need to provide companion objects which have builder implementations and implicitCanBuildFrom
objects (which can simply beGenericCanBuildFrom
s).EDIT:
GenericTraversablTemplate
mentioned above is needed because it first ensures that the collection will have thegenericBuilder
method called by theGenericCanBuildFrom
builder factory. Second, it ensures that the collection actually has the companion object of typeGenericCompanion
.