为什么play-json Reads
特性未声明为协变的:
trait Reads[+A]
相关要点:https://gist.github.com/robertberry/9410272
协方差/协方差会干扰隐式吗?
或者可选地,如何为密封特征编写
Reads
实例? https://gist.github.com/phadej/c60912802dc494c3212b 最佳答案
它可能是协变的,尤其是当您将Reads[A]
视为JsValue => A
的更丰富形式时。
但是...隐含。Reads[A]
不仅是的一种从JsValue
转换为A
的方式,而且是方式的。
所以如果我们有sealed trait Foo
case class Bar(a: Int)
case class Baz(b: Int)
如果定义了Reads[Bar]
,则(具有协方差)也将具有Reads[Foo]
。
这可能有点奇怪。object Foo {
implicit reads: Reads[Foo] =
implicitly[Reads[Bar]].orElse[implicitly[Reads[Baz]]]
}
object Bar {
implicit reads = Json.reads[Bar] // {"a":0}
}
object Baz {
implicit reads = Json.reads[Baz] // {"b":0}
def blah(jsValue: JsValue): Foo = jsValue.as[Foo]
}
object Main {
def blah(jsValue: JsValue): Foo = jsValue.as[Foo]
}
Baz.blah
和Main.blah
中发生了什么?前者使用Baz.reads
,而后者使用Foo.reads
,因为(复杂的)隐式解析顺序。
这是一个极端的情况,我仍然认为您可以为协方差做一个很好的论据,但是它的确显示了“可以将JSON解析为Foo
的东西”和“可以将JSON解析为所有可能的Foo
的东西”之间的区别。