Я хотел бы иметь возможность собирать объекты домена из признаков, в зависимости от различных свойств, которые могут иметь конкретные классы. Когда мои объекты изменяемы, это довольно просто. Например:
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
. Если у меня много конкретных классов и множество разных свойств, которые я мог бы использовать для смешивания, какая лучшая схема, чтобы избежать взлома кода шаблона?