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

标签 scala inheritance immutability

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

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实例而不知 Prop 体类型。

用不可变对象(immutable对象)实现这一点的最佳方法是什么?如果我很高兴只阅读属性,那么我可以执行以下操作:
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 , 例如。如果我有很多具体的类,以及我可能想要混合的很多不同的属性,那么避免样板代码爆炸的最佳方案是什么?

最佳答案

你可能有一些运气添加例如将 def withHitPoints(points: Int) 方法抽象为您的特征,该方法返回具有不同属性值的容器对象的副本。这将使用减少到类似:

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

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

关于scala - 不可变类层次结构中的多态更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8801818/

相关文章:

javascript - 从单独的文件扩展 JavaScript 类

objective-c - 线程安全:使数据结构不可变就足够了吗?

java - 我可以在 Play Framework 2 中使用 specs2 测试 Java Controller 吗?

C++ 类继承 : Functions

java - 巨大的随机数排序列表

c++ - 不直观的嵌套类继承

java - 如何创建一个抽象的、不可变的类?

javascript - 在 React 中将一个大数组包装在一个对象中以避免深度克隆是作弊吗?

scala - 在当前的 Scala 中,是否有更简洁的方法来执行 "lazy constructor pattern"

java - 如何覆盖 Scala 中的 toString 方法并将其替换为动态文本