通过Scala中的trait定义Enumeration对象的隐式格式

时间:2017-12-07 17:37:20

标签: scala object inheritance enums traits

我正在尝试为反序列化Enumerations的JSON值时要使用的多个对象定义隐式特征。我理解如何在一个对象中执行此操作,但我希望模拟此行为以保持我的代码DRY。我可以通过以下方式来实现这一目标:

object SomeEnum extends Enumeration {
  type SomeEnum = Value
  val FIRST: SomeEnum = Value("First")
  val SECOND: SomeEnum = Value("Second")
  implicit object SomeEnumFormat extends Format[SomeEnum] {
    def writes(o: SomeEnum): JsValue = JsString(o.toString)

    def reads(json: JsValue): JsResult[SomeEnum] = json match {
      case JsString(x) => JsSuccess(SomeEnum.withName(x.toLowerCase.capitalize))
      case _ => JsError()
    }
  }
}

以下是我一直在尝试的内容:

object SomeEnum extends Mappable {
  val FIRST: SomeEnum = Value("First")
  val SECOND: SomeEnum = Value("Second")
}

object SomeOtherEnum extends Mappable {
  val ABC: SomeOtherEnum = Value("Abc")
  val DEF: SomeOtherEnum = Value("Def")
}

trait Mappable extends Enumeration {
  implicit val enumMapper: JdbcType[Value] with BaseTypedType[Value] = MappedColumnType.base[Value,String](_.toString, this.withName)

  def unapply[Type](s: String): Option[Value] = values.find(s == _.toString)

  implicit object someFormat extends Format[Class[_ <: Mappable]] {
    def writes(o: Class[_ <: Mappable]): JsValue = JsString(o.toString)

    def reads(json: JsValue): JsResult[Value] = json match {
      case JsString(x) => JsSuccess(this.asInstanceOf[Mappable].withName(x.toLowerCase.capitalize))
      case _ => JsError()
    }
  }
}

我希望继承的特性会像为扩展特征的类提供隐式对象的模板版本一样,但我得到以下错误:

found   : Mappable#Value
required: Mappable.this.Value

如果我将返回类型的read放到JsResult[Mappable#Value]代码无法编译,因为没有找到指定枚举类型的隐式声明。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

我最初误解了发生的事情,以下是有效的解决方案

object SomeEnum extends Mappable {
  type SomeEnum = Value
  val FIRST: SomeEnum = Value("First")
  val SECOND: SomeEnum = Value("Second")
}

object SomeOtherEnum extends Mappable {
  type SomeOtherEnum = Value
  val ABC: SomeOtherEnum = Value("Abc")
  val DEF: SomeOtherEnum = Value("Def")
}

trait Mappable extends Enumeration {
  implicit val enumMapper: JdbcType[Value] with BaseTypedType[Value] = MappedColumnType.base[Value,String](_.toString, this.withName)

  def unapply[Type](s: String): Option[Value] = values.find(s == _.toString)

  implicit object someFormat extends Format[Value] {
    def writes(o: Value): JsValue = JsString(o.toString)

    def reads(json: JsValue): JsResult[Value] = json match {
      case JsString(x) => JsSuccess(withName(x.toLowerCase.capitalize))
      case _ => JsError()
    }
  }
}