的常見的伎倆是指從父到子類電流,是使用F-bounded polymorphism:
// Here `T` refers to the type of the current subclass
abstract class A[T <: A[T]]() {
this: T =>
def toJson(implicit writes: Writes[T]): JsValue = Json.toJson(this)
}
// We have to specify the current subclass in `extends A[B]`
case class B(myProperty: String) extends A[B]
object B { implicit val bFormat = Json.format[B] }
println(B("foo").toJson)
這會不會讓你打電話,雖然對toJson
任何通用A
:
val a: A[_] = B("foo")
println(a.toJson) // Doesn't compile with:
// No Json serializer found for type _$1.
// Try to implement an implicit Writes or Format for this type.
要解決此問題,您必須在創建對象時爲子類型保存Writes
:
abstract class A[T <: A[T]](implicit writes: Writes[T]) {
this: T =>
def toJson: JsValue = Json.toJson(this)
}
或可選擇地使用context bound符號:
abstract class A[T <: A[T] : Writes] {
this: T =>
def toJson: JsValue = Json.toJson(this)
}
而且,由於該F-界多態性東西只是一個實現細節,總是指的通用A
作爲A[_]
相當樣板-Y,你可以將這些代碼到中間abstract class
。
所以,一個完整的例子看起來是這樣的:
abstract class A() {
def toJson: JsValue
}
abstract class AImpl[T <: AImpl[T] : Writes] extends A {
this: T =>
def toJson: JsValue = Json.toJson(this)
}
case class B(myProperty: String) extends AImpl[B]
object B { implicit val bFormat: Format[B] = Json.format[B] }
val a: A = B("foo")
println(a.toJson)
您可以使用F-界多態性http://stackoverflow.com/questions/14741047/polymorphic-scala-return-type –
我會建議使用改爲類型類。例如。 http://argonaut.io/doc/codec/ – Reactormonk