まつもと ゆきひろ@トヨタケーラムです.

今日のお題は「モジュール」です.しばらく続いたオブジェクト指
向機能についての説明は,一応ここで終りです.
--
モジュール

rubyにはクラスの他にモジュールと呼ばれるものがある.rubyのモ
ジュールにはクラスに良く似ているが,3つの点で異なっている.

 (1) モジュールのインスタンスは作れない
 (2) モジュールのサブクラスは作れない
 (3) モジュールはmodule...endで定義する

実際,モジュールのクラスModuleはクラスのクラスClassのスーパー
クラスになっている.

で,モジュールの使われ方だが,大きく分けて二つある.ひとつは
メソッドや定数をまとめるためである.標準ライブラリの中では例
えばMathモジュールがこの働きをしている.

 ruby> Math.sqrt(2)
 1.41421
 ruby> Math::PI
 3.14159

あ,まだ説明していなかったが,`::'というのはそのモジュールや
クラスで定義されている定数を参照する演算子だ.モジュールで定
義されているメソッドや定数を利用するためには`include'を使う.

 ruby> include Math
 nil
 ruby> sqrt(2)
 1.41421
 ruby> PI
 3.14159

モジュールのもうひとつの使い方はmixinと呼ばれるものだ.こっ
ちはちょっと複雑なので,少し詳しく説明しよう.

ruby以外のオブジェクト指向言語には複数のスーパークラスから継
承する機能(多重継承)を持つものもあるが,rubyは意図的にこの機
能を持っていない.その代わりモジュールを使ったmixinという方
法で同じことを実現できる.

既に説明したようにモジュールはクラスと同じような働きをするも
ので,そこでの定義されたメソッドや定数は,継承こそできないも
のの,includeすることによって,他のモジュールやクラスに追加
できる.つまり,あるモジュールの定義をincludeすることによっ
て,そのクラスの性質を「混ぜ混む」ことができるわけだ.これを
mixinと呼んでいる.

rubyの標準ライブラリの中でmixinの代表はEnumerableである.こ
れのモジュールを要素を順に返す`each'というメソッド(イテレー
タ)を持つクラスにmixinすると,ソートや検索などの機能を追加す
ることができる.

多重継承とmixinの違いは以下の通りである.

  * モジュールはインスタンスを生成しない(抽象クラスであるこ
    とが保証される).

  * (主たる)継承関係がtree構造になることが保証される.

どちらもクラスの関係の複雑さを抑える働きがある.

rubyが多重継承を持っていない理由は,それが複雑さの原因になる
からだ.クラスが複数のスーパークラスを持ち,関係のネットワー
クを形成する状況は,大体において人間の頭には複雑すぎることが
多い.少なくとも僕の頭にとっては.

その点,mixinならもとのクラスに「付加したい特定の性質をまと
めたもの」としてすっきりとまとめることができる.

だから,多重継承のある言語でも実際はmixin的な形で,抽象的な
性質だけまとめたクラスを多重継承して,使うのが賢いやり方だと
いわれている.rubyはそれをもう一歩進めて,多重継承を無くして,
mixinだけを許すようにしているわけだ.