[英]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): Humanoid
到Humanoid
特性,並在子類中實現。
或等效地,如下所示:
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.