簡體   English   中英

Scala:從普通超類型復制案例類

[英]Scala: copy case class from common supertype

假設我有一個基本的實體特征

trait Entity {
  final val id: Long = IdGenerator.next()
  def position: (Double, Double)
}

然后可以使用其他一些(仍然是抽象的)功能進行擴展

sealed trait Humanoid { self: Entity =>
  def health: Double
  def name: String
}

最后,還有一些具體的案例類,其中混入了功能。

case class Human(
  position: (Double, Double),
  health: Double,
  name: String
)
  extends Entity with Humanoid {

}

有了這個,假設我需要定義事件特征,它封裝了從一個實體到另一個實體的某些動作

sealed trait Event[A, B] {
  final val timestamp: Long = System.currentTimeMillis

  def from: A
  def to: B

  def event: B => B
}

現在,有一個通用事件的案例類,它僅適用於Humanoid實體。

case class TakeDamage[A <: Entity, B <: Humanoid](damage: Int, from: A, to: B)
  extends Event[A,B] {
    val event = (ent: B) => {
      //a copy of ent with some parameters changed, e.g. health
    }
}

這應該是可行的,因為類人型超類型的所有實體都將具有必填字段(健康)。

在沒有太多樣板代碼的情況下,是否可以在scala中使用任何類型安全且不可變的方法來執行此操作? 還是我的抽象完全錯誤?

我能想到的唯一的“非丑陋”(即不涉及諸如反射和向下投射之類的臭技巧)的方法是將def copy(health: Double, name: String): HumanoidHumanoid特性,並在子類中實現。

或等效地,如下所示:

 object Humanoid {
    def copy [T <: Humanoid](from: T, health:Double, name: String): T = from match {
       case x: Human => x.copy (health=health, name=name)
    }
  }

第二種方法沒有很多好處,而且安全性較低(無法強制Humanoid每個實現都可以與copy ,而您必須依靠慣例和程序員的記憶,這幾乎從來都不是一件好事),因此,只要您有權訪問類的實現,我就會堅持使用舊的,好的方法重寫。

暫無
暫無

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

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