Scala - 是否可以在超类中定义隐式函数?

时间:2016-10-21 11:12:01

标签: scala playframework scala-implicits

我正在使用Scala Play编写Web服务。功能还可以,但我正在重构一些部分,以使我的代码更具可读性和清洁性。

我已经为每个实体类使用了隐式,使它们可以转换为Json。我还将toJson函数注入Seq[MyEntityClass],以便能够通过调用单个函数来生成Json数组。

看起来像这样:

case class MyModel(id: Option[Int], foo: String, bar: String)

object MyModel {
  implicit val writer = Json.writes[MyModel]
  implicit val reader: Reads[MyModel] = new Reads[MyModel] {
    def reads(json: JsValue): JsResult[MyModel] = {
      for {
        foo <- (json \ "foo").validate[String]
        bar <- (json \ "bar").validate[String]
      } yield MyModel(None, foo, bar)
    }
  }

  implicit def richMyModelSeq(apps: Seq[MyModel]) = new {
    def toJson:JsValue = Json.toJson(apps)
  }
  // ...
}

如何在超类中定义此代码,以便不为每个实体类重复此代码?

为什么这不起作用?

abstract class Jsonable {
  implicit val writer = Json.writes[Jsonable]

  implicit def richMyModelSeq(apps: Seq[MyModel]) = new {
    def toJson:JsValue = Json.toJson(apps)
  }
}
case class MyModel(id: Option[Int], foo: String, bar: String)

object MyModel extends Jsonable{
  implicit val reader: Reads[MyModel] = new Reads[MyModel] {
    def reads(json: JsValue): JsResult[MyModel] = {
      for {
        foo <- (json \ "foo").validate[String]
        bar <- (json \ "bar").validate[String]
      } yield MyModel(None, foo, bar)
    }
  }
  // ...
}

1 个答案:

答案 0 :(得分:0)

您可以使用以下内容: 类可以扩展特征,伴随对象可以扩展MyModelComp。

import play.api.libs.json._

trait MyModel {
  def id: Option[Int]
  def foo: String
  def bar: String
}

trait MyModelComp[M <: MyModel] {

  def cons: MyModel => M

  implicit val writer = Json.writes[MyModel]
  implicit def reader[M]: Reads[M] = new Reads[M] {
    def reads(json: JsValue): JsResult[M] = {
      for {
        foo <- (json \ "foo").validate[String]
        bar <- (json \ "bar").validate[String]
      } yield cons(new MyModel {
        override def foo: String = ???

        override def bar: String = ???

        override def id: Option[Int] = ???
      })
    }
  }
}