我正在尝试实现一个遵循相同习语的新集合类型
作为标准库,但我很难搞清楚如何处理
Builder
机制。我读过了优秀的"Architecture of Scala
Collections" doc
page,
但它不包括我的情况。
以下是我正在尝试做的简化版本:
import scala.collection.TraversableLike
import scala.concurrent.Future
trait AsyncMap[A, +B]
extends Traversable[(A, B)]
with TraversableLike[(A, B), AsyncMap[A, B]]
{
def empty: AsyncMap[A, B]
// This is the main difference from scala.collection.Map (an AsyncMap doesn't
// block while it checks if it contains an element for a given key).
def get(key: A): Future[Option[B]]
def +[B1 >: B](kv: (A, B1)): AsyncMap[A, B1]
}
编译上面的代码会给我一个错误:
error: overriding method newBuilder in trait TraversableLike of type => scala.collection.mutable.Builder[(A, B),AsyncMap[A,B]]; method newBuilder in trait GenericTraversableTemplate of type => scala.collection.mutable.Builder[(A, B),Traversable[(A, B)]] has incompatible type trait AsyncMap[A, +B] ^
我认为抱怨的是GenericTraversableTemplate
有一个具体的newBuilder
实现,其签名与之不兼容
TraversableLike
正在寻找的那个。我不明白的是我是怎么做的
可以绕过这个。
实施newBuilder: Builder[(A, B), Traversable[(A, B)]]
会产生这一点
错误:
error: overriding method newBuilder in trait TraversableLike of type => scala.collection.mutable.Builder[(A, B),AsyncMap[A,B]]; method newBuilder has incompatible type override def newBuilder: Builder[(A, B), Traversable[(A, B)]] = { ^
虽然实施newBuilder: Builder[(A, B), AsyncMap[A, B]]
会产生这一点
错误:
error: covariant type B occurs in contravariant position in type => scala.collection.mutable.Builder[(A, B),AsyncMap[A,B]] of method newBuilder override def newBuilder: Builder[(A, B), AsyncMap[A, B]] = { ^
我认为我采用后一种方法走上正轨,但我不确定如何做到 在这里指定方差。
我也试过让它看起来更像内部收藏品
实施一个
trait AsyncMapLike[A, +B, +This <: AsyncMapLike[A, B, This] with AsyncMap[A, B]]
,
但这种方法没有结果。
我应该承认我对Scala很新,而且我认为我理解它 类型系统我可能不知道某种类型的操作符或简单的设计模式 解决了这个问题。
非常感谢任何帮助。
可能相关的问题:
答案 0 :(得分:1)
正如mucaho帮我在上面的评论中发现的那样,事实证明我的问题是由缺少访问修饰符引起的。关于差异的错误消息对我来说仍然没有意义(我已经打开了一个关于它的新问题:Why does scalac only emit variance errors with certain access modifiers?),但当我用具体实现覆盖newBuilder
时是protected[this]
,一切都按预期工作(以前我一直试图公开)。
import scala.collection.mutable.Builder
import scala.collection.TraversableLike
import scala.concurrent.Future
trait AsyncMap[A, +B]
extends Traversable[(A, B)]
with TraversableLike[(A, B), AsyncMap[A, B]]
{
def empty: AsyncMap[A, B]
def get(key: A): Future[Option[B]]
def +[B1 >: B](kv: (A, B1)): AsyncMap[A, B1]
// This works!
override protected[this] def newBuilder: Builder[(A, B), AsyncMap[A, B]] = ???
}