假设我有一个基本的实体特征
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
}
}
这应该是可能的,因为Humanoid超类型的所有实体都将具有必需的字段(健康)。
scala中是否有任何类型安全且不可变的方法,没有太多的样板代码?或者我的抽象完全错了?
答案 0 :(得分:1)
我能想到的唯一“非丑陋”(即不涉及反思和向下转换等臭味的技巧)是将def copy(health: Double, name: String): Humanoid
添加到Humanoid
特征中,并在子类中实现它。 / p>
或等效地,像这样:
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
,你必须依赖约定和程序员的记忆,这几乎从来都不好,所以只要你有权访问类实现,我就会坚持使用旧的,好的方法覆盖。