2012-01-10 15 views
17

具体的なクラスが持つ可能性のあるさまざまなプロパティに従って、ドメインオブジェクトを特性からアセンブルすることができます。オブジェクトが変更可能な場合、これはかなり簡単です。例えば:特に不変クラス階層の多態的な更新

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 } 

、Iは、多形コンクリートタイプを知らなくても、任意の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を更新しています。具体的なクラスがたくさんあり、さまざまなプロパティが混在している場合、定型コードの爆発を避ける最良の方法は何ですか?

答えて

1

抽象的なdef withHitPoints(points:Int)メソッドを独自の特性に変換します。このメソッドは、異なるプロパティ値を持つコンテナオブジェクトのコピーを返します。これは次のように使用量を削減します。

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

しかし、そうでない場合は具象クラスごとのプロパティごとに余分な方法が必要になりますので、私はそれが本当にあなたの問題を解決するかわかりません。これはScalaのような静的な言語に対してはまったく気になりません(また、この特定の使用事例では不変性を気にしません)。ここでは不変の解決法が動的言語のより良い候補になるかもしれません。

+0

右のM具体的なクラスのN更新メソッドの混乱は、私が避けたいものでした。そしてあなたが指摘しているように、それは動的言語ではかなり簡単です。このユースケースは明らかに非常に簡素化されていますが、不変の継承階層で更新を混在させると、問題が発生することがよくあります。 –

+0

私はそれがScalaがうまく扱えないものだと主張するつもりはありませんが、私の経験上、頻繁に収穫されないシナリオです。もちろん、モデリングのこの時期にあなたが死んでいる場合を除きます。 –

+2

おそらく、私はSapir-Whorfのことは何度ですか?言語がうまく処理できないシナリオは、頻繁に切り取られないシナリオになります。 –

1

M個の具象クラスでN個の更新メソッドを避けたいと考えています。 しかし、私はこれはちょうど不可能であると思う痛みを伴う。コピーメソッドまたは少なくともすべての具象クラスのコンストラクタにアクセスする必要があります。どちらも抽象化することはできません。Case class copy() method abstraction 最後に、N x Mの定型文のコードが常に終了します。

関連する問題