覆盖方法并添加隐式参数

时间:2015-09-18 11:21:49

标签: scala

我有以下代码,我想知道是否可以删除令人讨厌的东西。如果我添加隐式参数,覆盖不起作用。

class FromEnumFormat[T <: Enum[T]] extends JsonFormat[T] {
  override def read(json: JsValue): T = readit(json)

  def readit(json: JsValue)(implicit m: Manifest[T]): T = {

    val EnumerationClass = m.runtimeClass.asInstanceOf[Class[T]]

    json match {
      case s: JsString if EnumerationClass.getEnumConstants.map(_.toString.toLowerCase).contains(s) => Enum.valueOf(EnumerationClass, s.value.toUpperCase()).asInstanceOf[T]
      case unknown => deserializationError(s"unknown Status: $unknown")
    }
  }

  override def write(obj: T): JsValue = JsString(obj.name().toLowerCase)
}

有没有办法摆脱这条线

override def read(json: JsValue): T = readit(json)

问题基本上是:隐式参数是方法签名的一部分吗?

更新: 代码没有编译。所以正确的解决方案应该是:

class FromEnumFormat[T<: Enum[T]] extends JsonFormat[T] {

 implicit val m: Manifest[T] = ???

  override def read(json: JsValue): T = {

    val EnumerationClass  = m.runtimeClass.asInstanceOf[Class[T]]

    json match {
      case s :JsString if EnumerationClass.getEnumConstants.map(_.toString.toLowerCase).contains(s) => Enum.valueOf(EnumerationClass ,s.value.toUpperCase()).asInstanceOf[T]
      case unknown => deserializationError(s"unknown Status: ${unknown}")
    }
  }

  override def write(obj: T): JsValue = {JsString(obj.name().toLowerCase)}
}

问题是如何访问Manifest?我正在使用Scala 2.10

更新: 发现问题是scala反射而不是暗示和覆盖,因此关闭了这个问题。

3 个答案:

答案 0 :(得分:2)

为了回答你的问题,隐式参数是方法签名的一部分。但是,因为它是隐含的,这意味着你可以调用def readit(json: JsValue)(implicit m: Manifest[T]): T函数而不提及它,只要它已在代码中的某处声明:

implicit val manifest = /* whatever a Manifest is*/
readit(jsonValue)

请您举例说明您想做什么?

答案 1 :(得分:2)

你的最终解决方案几乎是正确的,但是m位置错误,它应该是一个类参数:

class FromEnumFormat[T<: Enum[T]](implicit m: Manifest[T]) extends JsonFormat[T] {

  override def read(json: JsValue): T = {

    val EnumerationClass  = m.runtimeClass.asInstanceOf[Class[T]]

    json match {
      case s :JsString if EnumerationClass.getEnumConstants.map(_.toString.toLowerCase).contains(s) => Enum.valueOf(EnumerationClass ,s.value.toUpperCase()).asInstanceOf[T]
      case unknown => deserializationError(s"unknown Status: ${unknown}")
    }
  }

  override def write(obj: T): JsValue = {JsString(obj.name().toLowerCase)}
}

这样编译器可以在创建具有特定枚举的FromEnumFormat时插入它:

val format = new FromEnumFormat[TimeUnit]

但是,如果要创建通用FromEnumFormat[T],则必须将implicit m: Manifest[T]作为参数传递:

def doSomethingWithFormat[T <: Enum[T]](implicit m: Manifest[T]) = {
  val format = new FromEnumFormat[T]
  ...
}

答案 2 :(得分:1)

隐含参数不完全部分签名。 但是所以你不能通过重载来添加隐式参数。

这就是原因。多参数列表语法只是一种语法糖。代码

def readit(json: JsValue)(implicit m: Manifest[T]): T = ???

变得黯然失色

def readit(json: JsValue): Function1[Manifest[T], T] = {
  def inner(implicit m: Manifest[T]): T = ???
  inner
}

因为您看到readit的真实类型与read的类型不匹配,因此它不是正确的覆盖。

<强> UPD。

正如Alexey正式指出的那样,多个参数列表有助于类型签名(请参阅scala规范的4.6 Function Declarations and Definitions部分)。

  

函数声明的形式为def fpsig:T,其中f是函数的名称,psig是其参数签名,T是其结果类型。

     

参数签名由可选的类型参数子句组成   [tps],后跟零个或多个值参数子句   (ps1)…(psn)