作者: HIDAKA Takahiro
日時: 2002/4/07(03:39)
 ひだかです。

kikwai@... (機械伯爵) wrote:

>  RubyのMix-inは、まだちょっと理解できてないので、どなたか・・・

 Ruby の Mix-in は制限された多重継承の一種です。

  module M
    def f
    end
  end

  class C
    include M
  end

とやれば、クラスCにインスタンスメソッドfが追加されます。

 Ruby の Class は単一継承ですが、複数のクラスで実装を
共有するために、Mix-in を使うことができます。


 ではただの多重継承との違いはというと、ModuleとClassの
違いに還元できると思います。

 Ruby の Module と Class の違いには、

・Class を include することはできない
・Module はインスタンスを生成できない
・Module は他の Module/Class を継承できない(include はできる)

と言った点があげられます。


 機能的には、実際のところC++ での virtual public 継承と
ほとんど変わらないことができるとは思います。
ですが、Mix-in というのは、他のクラスに機能を追加するための
付加的なもの、という意味合いがあります。つまり、単独では
機能しなくて、includeした側のクラスのほかのメソッドと協調して
動作することがほとんどです。

# Module で完結していて、他のメソッドと無関係なものを
# 追加したい例ってあるのかな?

 たとえば、Ruby組み込みのComparableモジュールでは、
クラスの <=> 演算子を定義しておけば、その他の比較演算子を
全部定義してくれます。ですが、Comparable だけが存在しても
全然使い道がありません。

 このように、単独では意味をなさないですから、インスタンスを
生成できる必要はありません。C++ なら純粋仮想関数として 
比較メソッドを宣言するようなクラスになることでしょう。

 そのようなものを、Mix-in module として定義することで、

・Mix-inされるモジュール自身は「もの」ではない
・include する側のクラスから見ても、モジュールとの is-a 関係は弱い
・でも実装は利用したい

ということを明示できるようになるわけです。


 まとめると、多重継承したい場合にはいくつかの理由があると
思うのですが、

・単に実装を共有するための都合でクラス階層が深くなる
・クラス階層を横断する形で共有するコードが書きにくい
  (= さらに階層が深くなる)

といった問題を解決できるのが Mix-in ということに
なると思います。

 あれ、まとまっているのかな(^_^;;;

-- 
ひだかたかひろ  cv8t-hdk@...-net.or.jp