为什么玩JSON的Reads
特质不宣协:为什么Reads没有声明协变?
trait Reads[+A]
相关要点:https://gist.github.com/robertberry/9410272
是否协方差/逆变干扰implicits?
或者可选地,如何编写密封特征的Reads
实例? https://gist.github.com/phadej/c60912802dc494c3212b
为什么玩JSON的Reads
特质不宣协:为什么Reads没有声明协变?
trait Reads[+A]
相关要点:https://gist.github.com/robertberry/9410272
是否协方差/逆变干扰implicits?
或者可选地,如何编写密封特征的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
“。
假设Reads
是协变的。我有一个简单的类型层次:
sealed trait Foo { def name: String }
case class Bar(name: String, i: Int) extends Foo
case class Baz(name: String, c: Char) extends Foo
而对于case类的一个实例Reads
:
import play.api.libs.functional.syntax._
import play.api.libs.json._
implicit val readsBar: Reads[Bar] = (
(__ \ 'name).read[String] and (__ \ 'i).read[Int]
)(Bar.apply _)
但Bar <: Foo
,所以Reads[Bar] <: Reads[Foo]
,这是没有意义的,我没有说什么关于如何解码Baz
,所以我显然实际上没有Reads[Foo]
。
更好的问题可能是为什么Reads
不是逆变。
但是,如果我有非隐式的'readsBar:Reads [Bar]'和'readsBaz:Reads [Baz]':那么'readsFoo = readsBar或Else readsBaz'不起作用。但是'readsFoo = readsBar.map(x => x)或者elsese readsBaz.map(x => x)'是可以的。在这里我看到了协变映射。 – phadej 2014-08-29 18:24:04
这仍然困扰我,我写了一个小小的要点,希望澄清这个问题:https://gist.github.com/phadej/c60912802dc494c3212b – phadej 2014-10-08 17:59:18
我不这样解释就够了。你仍然有一种将JSON转换为'Foo'的方式,所以'Reads [Bar]'*'是* Reads [Foo]'。 – 2015-10-04 01:49:00
谢谢,暗示就是这样,就像我想的那样。你能评论一下这个要点吗?如果你写一个'读取[Child] .map(x => x)'或'读取[Child] .as [Reads [Parent]]',你的意见是什么? – phadej 2015-10-05 07:49:23
@phadej,你的意思是'.asInstanceOf'?无论如何,我认为扩展类型并不是什么坏事。唯一的问题是如果它是自动完成的。 – 2015-10-05 13:32:18