Scala的类型定义,如方法调用

时间:2017-12-04 12:56:04

标签: scala

我正在研究spray-json示例,最后一行val color = json.convertTo[Color]有一个函数调用,它指定了类型类型?几乎看起来像将类型定义分配给常量。在这种情况下,有人可以解释那里发生了什么吗?

case class Color(name: String, red: Int, green: Int, blue: Int)
object MyJsonProtocol extends DefaultJsonProtocol {
  implicit val colorFormat = jsonFormat4(Color)
}

import MyJsonProtocol._
import spray.json._

val json = Color("CadetBlue", 95, 158, 160).toJson
val color = json.convertTo[Color]

由于

1 个答案:

答案 0 :(得分:3)

目前尚不清楚到底有什么不清楚。您json变量的类型为JsValue。该类具有指定为

的通用convertTo方法
def convertTo[T :JsonReader]: T = jsonReader[T].read(this)

此代码表示可以为任何类型convertTo调用T,在上下文中可以看到类型为JsonReader[T]的隐式对象。所以这与一些编译魔术实际上是与

相同的代码
  def convertTo[T](implicit jsonReader: JsonReader[T]): T = jsonReader.read(this)

那么这个诀窍究竟是什么呢?请考虑您是Spray JSON库的作者。显然,有许多类型无法从JSON中合理解码(例如,解码Thread究竟是什么意思?)。因此,您希望JsValue.convertTo方法成为"类型安全"在某种意义上,您只允许解码至少可能在理论上解码的类型。不幸的是,自动决定这100%是一项相当艰巨的任务。 Still Spray JSON(以及许多其他Scala JSON库)提供了一些近似值。我们的想法是,您声明了一个type class JsonReader[T],它正好对此属性进行编码 - 类型T可以从JSON解码。然后,您需要仅解码为类型类成员的那些类型。 Scala中的这种类型类通常使用implicits来实现,即您不会强制显式传递证据,而是依赖于编译器来查找证据。 Althoug经常编译器只能通过上下文推断出正确的泛型类型替换,在这种特殊情况下没有上下文,所以你必须明确指定类型。

注意行

implicit val colorFormat = jsonFormat4(Color)

使用另一个强大的Scala技巧:宏。 Spray JSON提供了一个宏库,可以自动为多种类型生成类型类证据。