Mongodb 获得;“不兼容类型”;在返回一个对象时
我在写剧本!2.1使用ReactiveMongo的应用程序。每个可持久化的case类都有一个对象,该对象包含两个隐式对象,实现了BSONReader[…]和BSONWriter[…],每个case类都有返回这些对象的方法:Mongodb 获得;“不兼容类型”;在返回一个对象时,mongodb,scala,playframework-2.0,Mongodb,Scala,Playframework 2.0,我在写剧本!2.1使用ReactiveMongo的应用程序。每个可持久化的case类都有一个对象,该对象包含两个隐式对象,实现了BSONReader[…]和BSONWriter[…],每个case类都有返回这些对象的方法: trait Persistable { implicit def getReader: BSONReader[Persistable] implicit def getWriter: BSONWriter[Persistable] val coll
trait Persistable {
implicit def getReader: BSONReader[Persistable]
implicit def getWriter: BSONWriter[Persistable]
val collectionName: String
}
case class MyObj () extends Persistable {
override val collectionName: String = MyObj.collectionName
override def getReader: BSONReader[MyObj] = MyObj.MyObjBSONReader
override def getWriter: BSONWriter[MyObj] = MyObj.MyObjBSONWriter
}
object MyObj{
val collectionName: String = "MyObj"
implicit object MyObjBSONReader extends BSONReader[MyObj] {
def fromBSON(document: BSONDocument): MyObj = {
val doc = document.toTraversable
new MyObj(
)
}
}
implicit object MyObjBSONWriter extends BSONWriter[MyObj] {
def toBSON(myObj: MyObj) = {
BSONDocument(
)
}
}
出于某种原因,getReader似乎工作正常,但getWriter出现错误:
类型的trait Persistable中重写方法getWriter=
resactivemongo.bson.handlers.BSONWriter[models.persistable.persistable];
方法getWriter的类型不兼容
我做错了什么?两者似乎都有相似的签名。
另一个提示是,如果从getWriter中删除返回类型,则在eclipse中会出现complie time错误:
类型失配;找到:models.persistable.MyObj.MyObjBSONWriter.type必需:
reactivemongo.bson.handlers.BSONWriter[models.persistable.persistable]
更新:
我按照@AndrzejDoyle下面所说的那样做了,但是作为本练习的核心的Persister的实现抱怨道:
def insert(persistable: Persistable) = {
val collection = db(persistable.collectionName)
import play.api.libs.concurrent.Execution.Implicits._
implicit val reader = persistable.getReader
implicit val writer = persistable.getWriter
collection.insert(persistable)
}
错误:
特征持久化类型
参数
这是由于协方差和逆变换 mongodb阅读器定义为
BSONReader[+DocumentType]
。泛型参数中的+表示该类在该参数中是协变的。或者更全面地说
如果B
是a
的子类,则BSONReader[B]
是BSONReader[a]
的子类
因此,您可以在需要BSONReader[Persistable]
的任何地方使用BSONReader[MyObj]
另一方面,编写器是反向的:BSONWriter[-DocumentType]
。这意味着
如果B
是a
的子类,则BSONWriter[B]
是BSONWriter[a]
的超类
因此,您的BSONWriter[MyObj]
不是BSONWriter[Persistable]
的子类,因此不能代替它使用
这在一开始可能会让人感到困惑(即“为什么反向变化是有意义的?”)。然而,如果你想想这些类在做什么,它就会变得更清晰。读取器可能会生成其泛型参数的某个实例。然后,调用方可能希望它生成一个可持久化的
——如果您有一个专门生成MyObj
的版本,那么这就可以了
另一方面,编写器可能被赋予了其泛型参数的对象。具有BSONWriter[Persistable]
的调用方将调用write()
方法,传入要写入的Persistable
的实例。您的实现只能编写MyObj
的实例,因此它实际上与接口不匹配。另一方面,BSONWriter[Object]
将是任何BSONWriter的子类,因为它可以(从类型角度)接受任何类型作为参数
根本的问题似乎是你的
持久性
特征比你预期的要松散。您可能希望每个实现返回一个在自身上参数化的读写器,而不是通常在Persistable
上。您可以通过以下方式实现此目的:
trait持久化[T
trait Persistable[T <: Persistable[T]] {
implicit def getReader: BSONReader[T]
implicit def getWriter: BSONWriter[T]
val collectionName: String
}