Java world(より正確には、多重継承/ミックスインがない場合)では、経験則は非常に単純です:「クラス継承よりもオブジェクトコンポジションを優先する」。
特にscalaでミックスインも検討した場合、それがどのように変更されるかを知りたいですか?
ミックスインは多重継承の方法と見なされますか、それともより多くのクラス構成と見なされますか?
「クラス構成よりもオブジェクト構成を優先する」(またはその逆)ガイドラインもありますか?
オブジェクトコンポジションでも機能する可能性があるときに、人々がミックスインを使用(または乱用)する例をかなり見ましたが、どちらが優れているかは必ずしもわかりません。あなたはそれらで非常に似たようなことを達成できるように私には思えますが、いくつかの違いもあります、いくつかの例:
簡単な答えは「状況によって異なります」ですが、これまたはそれが優れている場合は、おそらくいくつかの典型的な状況があります。
これまでに思いついたガイドラインのいくつかの例(2つの特性AとBがあり、AがBのいくつかの方法を使用したいと仮定):
多くの場合、ミックスインの方が簡単(および/または冗長性が低い)のように見えますが、「神のクラス」や2つのartimaの記事で説明されているその他の落とし穴もあると確信しています。 パート1 =、 パート2 (ところで、他の問題のほとんどは、scalaには関係がない/それほど深刻ではないようです)。
このようなヒントは他にもありますか?
人々がミックスインで抱える問題の多くは、クラス定義に抽象特性のみをミックスインし、オブジェクトのインスタンス化で対応する具象特性をミックスインする場合、Scala)で回避できます。時間。例えば
trait Locking{
// abstract locking trait, many possible definitions
protected def lock(body: =>A):A
}
class MyService{
this:Locking =>
}
//For this time, we'll use a Java.util.concurrent lock
val myService:MyService = new MyService with JDK15Locking
この構成には、推奨するものがいくつかあります。まず、特性機能のさまざまな組み合わせが必要になるため、クラスが爆発的に増加するのを防ぎます。次に、モックオブジェクトと同様に、「何もしない」具体的な特性を作成して組み合わせることができるため、簡単にテストできます。最後に、使用されているロック特性を完全に隠し、そのロックが行われている場合でも、サービスの利用者から隠しました。
ミックスインの主張されている欠点のほとんどを乗り越えてきたので、ミックスインと構成の間のトレードオフがまだ残っています。私自身は、通常、仮想のデリゲートオブジェクトが含まれているオブジェクトによって完全にカプセル化されるかどうか、または共有されて独自のライフサイクルを持つ可能性があるかどうかに基づいて決定します。ロックは、完全にカプセル化されたデリゲートの良い例です。クラスがロックオブジェクトを使用してその内部状態への同時アクセスを管理する場合、そのロックは含まれているオブジェクトによって完全に制御され、クラスのパブリックインターフェイスの一部としてアドバタイズされません。このように完全にカプセル化された機能については、ミックスインを使用します。データソースのように共有されるものには、合成を使用します。
あなたが言及していない他の違い:
( プログラミングScala )
特定のトレイトが他のクラスの親として最も頻繁に使用され、子クラスが親トレイトとして動作することがわかった場合は、代わりにそのトレイトをクラスとして定義して、この論理関係をより明確にすることを検討してください。
(前者はリスコフの置換原則に基づく継承のより正確な定義であるため、is aではなくbehaves asと言いましたを参照] Martin2003]、例えば。)
[Martin2003]:Robert C. Martin、アジャイルソフトウェア開発:原則、パターン、および実践、Prentice-Hall、2003
trait
)にはコンストラクターパラメーターがありません。したがって、 アドバイス、まだプログラミングScalaから :
適切なデフォルト値に初期化できない特性の具体的なフィールドは避けてください。
代わりに抽象フィールドを使用するか、コンストラクターを使用してトレイトをクラスに変換します。
もちろん、ステートレス特性には初期化に関する問題はありません。優れたオブジェクト指向設計の一般原則は、構築プロセスが終了した瞬間から、インスタンスが常に既知の有効な状態にある必要があることです。
オブジェクトの--- [initial stateに関する最後の部分は、クラス(およびクラス構成)と特性のどちらを決定するのに役立つことがよくあります。 (およびミックスイン)特定の概念。