我有以下代码,我想知道是否可以删除令人讨厌的东西。如果我添加隐式参数,覆盖不起作用。
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反射而不是暗示和覆盖,因此关闭了这个问题。
答案 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)
。