簡體   English   中英

在Scala中,引用Abstract超級類中的子類

[英]In Scala, Refer to Subclass in Abstract Super Class

有沒有辦法讓超類中的this關鍵字引用該類的子類? 具體來說,我正在嘗試執行以下操作(Json指的是Play的Json庫):

abstract class A() {
  def toJson[T](implicit writes: Writes[T]): JsValue = Json.toJson(this)
}

case class B(myProperty: String) extends A
object B { implicit val bFormat = Json.format[B] }

這將產生錯誤, No Json serializer found for type A. Try to implement an implicit Writes or Format for this type. 就是說它不能序列化類型為A的對象,這很有意義。 的目標,但是,對於thisJson.toJson(this)來指代亞類(其在此實例中,是B )。

有什么辦法可以做到這一點? 如果不是,是否有其他方法可以在超類中實現Json.toJson(...)方法,而不必在子類(以及A所有其他子類)中實現?

從父級引用當前子類的常見技巧是使用F界多態性

// 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)

但是,這將不允許您為任何通用A調用toJson

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)
}

或者使用上下文綁定表示法:

abstract class A[T <: A[T] : Writes] { 
  this: T =>
  def toJson: JsValue = Json.toJson(this)
}

並且由於這種F界多態性只是實現細節,並且總是將通用A引用為A[_] ,因此您可以將此代碼移至中間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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM