Ответ 1
Это может быть ковариантным, особенно если вы рассматриваете Reads[A]
как более богатую форму JsValue => A
.
Но.... имплицитность.
Reads[A]
- это не просто a способ конвертировать из JsValue
в A
, это способ.
Итак, если бы мы имели
sealed trait Foo
case class Bar(a: Int)
case class Baz(b: Int)
Если вы определили a 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
".