Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mongodb 获得;“不兼容类型”;在返回一个对象时_Mongodb_Scala_Playframework 2.0 - Fatal编程技术网

Mongodb 获得;“不兼容类型”;在返回一个对象时

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

我在写剧本!2.1使用ReactiveMongo的应用程序。每个可持久化的case类都有一个对象,该对象包含两个隐式对象,实现了BSONReader[…]和BSONWriter[…],每个case类都有返回这些对象的方法:

  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
}