Scala:从常见的超类型复制案例类

时间:2016-01-08 11:15:24

标签: scala generics types polymorphism

假设我有一个基本的实体特征

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中是否有任何类型安全且不可变的方法,没有太多的样板代码?或者我的抽象完全错了?

1 个答案:

答案 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,你必须依赖约定和程序员的记忆,这几乎从来都不好,所以只要你有权访问类实现,我就会坚持使用旧的,好的方法覆盖。