不可变类层次结构中的多态更新

我希望能够根据具体类可能具有的各种属性从特征组装域对象。 当我的对象是可变的时,这是非常简单的。 例如:

trait HasHitPoints { var hitPoints: Int = 100 }
trait HasBearing { var bearing: Double = 0 }

class Ship extends HasHitPoints with HasBearing
class Base extends HasHitPoints

val entities = new Ship :: new Base :: Nil
entities.collect { case h: HasHitPoints => h.hitPoints += 10 }

特别是,我可以在不知道具体类型的情况下多态地读取或更新任何HasHitPoints实例。

用不可变对象实现这个最好的方法是什么? 如果我很高兴阅读这些属性,那么我可以执行如下操作:

trait HasHitPoints { val hitPoints: Int }
trait HasBearing { val bearing: Double }

case class Ship(hitPoints: Int, bearing: Double) extends HasHitPoints with HasBearing
case class Base(hitPoints: Int) extends HasHitPoints

val things = Ship(50, 0) :: Base(100) :: Nil

val totalHitPoints = things.collect { case h: HasHitPoints => h.hitPoints }.sum

另外,我可以很容易地修改使用具体的类copy ,如果我知道确切类型。 例如,困难的部分是更新任意的HasHitPoints 。 如果我有很多具体的类和许多不同的属性,我可能喜欢混入,那么避免模板代码爆炸的最佳方案是什么?


你可能会有一些运气,用你的traits添加一个带有HitPoints(points:Int)方法的抽象def方法,它会返回一个具有不同属性值的容器对象的副本。 这减少了使用情况,如下所示:

val damagedActors = actors map { actor => actor.withHitPoints( actor.hitPoints - 10 ) }

但是否则需要为每个具体类的每个属性额外添加一个方法,所以我不确定它是否真的解决了您的问题。 这对于像Scala这样的静态语言来说并不合适(我也不会为这个特定的用例打扰不可变性); 这里一个不可变的解决方案可能是动态语言的更好选择。


您希望避免M个具体类中的N个更新方法。 然而痛苦的我觉得这是不可能的。 您将需要访问复制方法或至少每个具体类的构造函数。 它们都不能像以下讨论的那样被抽象化:Case class copy()方法抽象所以最终你总是会得到N×M'样板'代码。


对于死灵法则不好意思,但值得指出的是,这是可行的使用F-bound多态性:

  trait HasHitPoints[Self <: HasHitPoints[Self]] { 
    val hitPoints: Int 
    def updateHitpoints(f: Self => Int): Self
  }
  trait HasBearing { val bearing: Double }

  case class Ship(hitPoints: Int, bearing: Double)
      extends HasHitPoints[Ship]
      with HasBearing {
    override def updateHitpoints(f: Ship => Int): Ship = copy(hitPoints = f(this))
  }
  case class Base(hitPoints: Int) extends HasHitPoints[Base] {
    override def updateHitpoints(f: Base => Int): Base = copy(hitPoints = f(this))
  }

  val things = Ship(50, 0) :: Base(100) :: Nil

  val heal = things.map(_.updateHitpoints(_.hitPoints + 10))

  val totalHitPoints = heal.map(_.hitPoints).sum
链接地址: http://www.djcxy.com/p/82685.html

上一篇: Polymorphic updates in an immutable class hierarchy

下一篇: running compact framework code on desktop computer