我有以下代码:
trait DBO
trait BSONWriter[S]
trait HasWriter {
implicit def writer[T <: BSONWriter[_ <: DBO]]: T
}
一切都很好!除非我将其混合到我的objects
中,所有集合中的map
方法以及在所有这些对象及其伴随类中隐式使用CanBuildFrom
的其他内容现在都会显示错误消息:
- 模糊隐含值:特征中的方法编写者保存类型[T&lt;:reactivemongo.bson.handlers.BSONWriter [_&lt ;: traits.DBO]] =&gt; T和方法canBuildFrom对象Buffer类型[A] =&gt; scala.collection.generic.CanBuildFrom [scala.collection.mutable.Buffer.Coll,A,scala.collection.mutable.Buffer [A]] 匹配预期类型 scala.collection.generic.CanBuildFrom [scala.collection.mutable.Buffer [models.world.Star],traits.IsInWorld 使用org.bundlelib.traits.Groupable {def asBSON: reactivemongo.bson.AppendableBSONDocument},即]
现在我不明白,为什么?混淆隐式方法的签名是不同的!我该如何防止这种情况?
答案 0 :(得分:7)
我认为一个简短的例子将显示问题:
trait Foo
trait Implicits {
implicit def b[T <: String]: T
implicit def run = implicitly[Foo]
}
这个编译正确 - 所以发生了什么?使用-Xprint:typer
:
implicit def run: foo.Foo = scala.this.Predef.implicitly[foo.Foo](Implicits.this.b[Nothing])
问题是Nothing
(以及其他类型,就编译器而言),都是Foo
和<: String
。 b
的类型过于多态,因此它基本匹配任何隐含的内容。这就是您的示例中发生的情况:Nothing
同时是T <: BSONWriter[_ <: DBO]
和CanBuildFrom[...]
。
我想我给你的建议是不要制作具有多态性的隐式方法。在您的示例中,我实际上想知道您是否真的希望writer
具有多态性。也许这就是你想要的?
trait HasWriter[T <: BSONWriter[_ <: DBO]] {
implicit def writer: T
}
这将避免隐含的问题。