[解決済み] scalaのミキシンとコンポジション
質問
javaの世界では(正確には多重継承やミキシンがない場合)、「クラス継承よりもオブジェクト合成を優先する」という非常にシンプルな経験則があります。
特にscalaの場合、mixinも考慮するとどう変わるのか知りたいのですが?
mixinは多重継承の方法として考えられているのでしょうか、それとももっとクラス構成が多いのでしょうか?
また、quot;Favor object composition over class composition" (or the other way around) guidelineがあるのでしょうか?
私は、オブジェクトの構成でも仕事ができるのに、人々がミキシンを使用(または乱用)している非常に多くの例を見てきましたし、どちらが良いのか常にわかりません。これらで非常に似たようなことを達成できるように思えますが、いくつかの違いもあり、いくつかの例もあります。
- 可視性 - mixin では、すべてが公開 API の一部になりますが、合成の場合はそうではありません。
- 冗長性 - ほとんどの場合、mixinは冗長性が少なく、少し使いやすいですが、必ずしもそうとは限りません(例:複雑な階層で自己型も使用する場合など)。
短い答えは「It depends"」ですが、おそらく、これかこれが良いという典型的な状況がいくつかあると思います。
私がこれまでに思いついたガイドラインのいくつかの例(私が2つの特性AとBを持っていて、AがBからいくつかのメソッドを使用したいと仮定しています)。
- BのメソッドでAのAPIを拡張したい場合はミキシンを、そうでない場合はコンポジションを使用します。しかし、作成するクラス/インスタンスがパブリック API の一部でない場合は役に立ちません。
- ミキシンを必要とするいくつかのパターンを使いたい場合(例えば スタッカブル・トレイト・パターン など) ならば、簡単に決定できます。
- 循環的な依存関係がある場合、自己型を持つmixinが役に立ちます。(私はこの状況を避けようとしていますが、いつも簡単というわけではありません)
- もし、動的で、実行時にどのように合成を行うかを決定したいのであれば、オブジェクト合成を使用します。
多くの場合、mixinの方が簡単(および/または冗長でない)ように見えますが、artimaの2つの記事で説明されている"God class"などのように、いくつかの落とし穴があることも間違いないでしょう。 パート 1 , パート2 (ちなみに、他の問題のほとんどは、scalaには関係ない/それほど深刻ではないようです).
このようなヒントは他にもあるのでしょうか?
どのように解決するのですか?
Scalaでは、クラス定義に抽象的な特徴を混ぜるだけにして、オブジェクトのインスタンス化時に対応する具体的な特徴を混ぜれば、mix-inで発生する問題の多くを回避することが可能です。 例えば
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
この構成には、いくつかの利点があります。 第一に、様々な機能の組み合わせが必要となるため、クラスが爆発的に増加するのを防ぐことができます。 第二に、モックオブジェクトのように何もしない具象トレイトを作成し混ぜることができるので、簡単にテストすることができます。 最後に、使用されているロッキングトライトはもちろん、ロッキングが行われていることさえも、サービスの利用者から完全に隠蔽されています。
ミックスインの欠点のほとんどを克服したので、ミックスインとコンポジションの間のトレードオフがまだ残っています。
ミックスインとコンポジションの間のトレードオフが残っています。 私自身は、通常、仮想的なデリゲート オブジェクトが含むオブジェクトによって完全にカプセル化されるかどうか、または潜在的に共有されてそれ自身のライフサイクルを持つことができるかどうかに基づいて決定を下します。 ロックは、完全にカプセル化されたデリゲートの良い例を提供します。 クラスがロックオブジェクトを使用して内部状態への同時アクセスを管理する場合、そのロックは包含オブジェクトによって完全に制御され、そのクラスのパブリックインターフェースの一部として、ロックやその操作が公告されることはありません。このような完全にカプセル化された機能については、私はミックスインを使用します。 データソースのような共有されるものには、コンポジションを使用します。
関連
-
[解決済み] mixinとは何か、なぜ有用なのか?
-
[解決済み] Scalaのcase classとclassの違いは何ですか?
-
[解決済み] Rubyの継承とミキシンの比較
-
[解決済み] Scalaの配列の初期化
-
[解決済み] scalaは推論される型の「許容される複雑さ」にどのような制限を設けているのでしょうか?
-
[解決済み] Scalaの慣用表現「flatmap that s*** 」はどこから来たのか?
-
[解決済み] Rubyのモジュール/ミキシンからクラスメソッドを継承する
-
[解決済み] scala で複数の case class をマッチングさせる
-
[解決済み] 上位互換型はどんなときに役立つのか?
-
[解決済み] scalaのマップを反復処理するには?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Scalaの配列の初期化
-
[解決済み] Scalaです。リスト[Future]からFuture[List]への変換は、失敗したFutureを無視する。
-
[解決済み] HDFSではなく、ローカルファイルをsc.textFileで読み込む方法
-
[解決済み] Scalaでmapを使用してインデックスを受け取るにはどうしたらいいですか?
-
[解決済み] build.sbtとbuild.scalaの違いは何ですか?
-
[解決済み] 機能的デザインパターン【終了しました
-
[解決済み] SBTの正しい使い方を教えてください。
-
[解決済み] Scala で複数の暗黙の引数を持つ関数を定義する
-
[解決済み] 依存性注入のためのリーダーモナド:複数の依存性、ネストされた呼び出し
-
[解決済み] 複数の先物を待つには?