如何在 Scala 中定义自定义集合接口而不定义实现?

发布于 2024-10-10 12:50:59 字数 440 浏览 2 评论 0原文

我正在尝试在 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

昔日梦未散 2024-10-17 12:50:59

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

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

你需要做的是:

  1. CustomCollection[A] 继承 TraversableLike
  2. CustomCollection[A] 继承 GenericTraversableTemplate
  3. CustomCollection 的伴生对象,并添加一个返回 GenericCanBuildFrom 的隐式对象
  4. CustomCollection 伴生中的构建器提供默认实现

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

编辑:

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

If you want map to return a more specific collection type, then you should also inherit TraversableLike, with the second type parameter (representation type) set to CustomCollection[A].

Next, map requires an implicit parameter of type CanBuildFrom. It will look in the companion object of CustomCollection to find a conforming implicit value of that type. If you take a look at the source code of Seq classes, you will see that their companions provide CanBuildFrom objects of type GenericCanBuildFrom which forwards the call for the builder back to the collection that requested the builder. That way, the dynamic type of return type of Seq transformer methods (e.g. map) is always the same as the type of the sequence itself.

What you have to do is:

  1. Make CustomCollection[A] inherit TraversableLike
  2. Make CustomCollection[A] inherit GenericTraversableTemplate
  3. Make a companion object of CustomCollection and add an implicit which returns a GenericCanBuildFrom
  4. Provide a default implementation for the builder in the CustomCollection companion

The implementers of CustomCollection will need to provide companion objects which have builder implementations and implicit CanBuildFrom objects (which can simply be GenericCanBuildFroms).

EDIT:

GenericTraversablTemplate mentioned above is needed because it first ensures that the collection will have the genericBuilder method called by the GenericCanBuildFrom builder factory. Second, it ensures that the collection actually has the companion object of type GenericCompanion.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文