Kamuycikap - SentenceDataBase

日々の勉強の記録を気分で書き綴るブログ

モジュールとMix-in

クラスの先祖には、多くの組み込みメソッドが定義されている。
注意すべきなのが、オブジェクト「Object」は全てのクラスのスーパークラスにインクルードされるKernelモジュールのメソッドである。
Objectは全てのクラスのスーパークラスであるため、KernelからObjectに追加されるメソッドは全てのクラスで利用できる。
これらのメソッドはRubyの非常に重要な部分を構成する。

モジュールとMix-inという言葉はほぼ同義語である。
モジュールは、Rubyプログラムの外部にあるメソッドと定数の集まりである。
単に名前空間の管理に使うことも出来るが、もっとも多い使い方は、モジュールの機能を「include」を利用してインクルードする方法となる。
この場合、モジュールはMix-inとして使われる。

モジュールを名前空間の管理に使う例として、Mathモジュールの使用法が上げられる。
例えば、円周率であるPiを定義する場合、Mathモジュールをインクルードする必要は無い。
単にMath:PIを定数として利用することが出来る。

Mix-inを利用すると、多重継承に伴う問題に悩まされずに、そのいくつかの恩恵を享受することが出来る。
Mix-inは制限された形の多重継承と考えること出来るが、作者のまつもとゆきひろ氏は、これを「実装の共有を伴う単純継承」と呼んでいる。

includeでは、名前空間(モジュール)の機能が現在の空間に追加される。
extendメソッドでは、モジュールの機能がオブジェクトに追加される。
includeでは、モジュールのメソッドをインスタンスメソッドとして利用出来るようになる事に対し、extendでは、クラスメソッドとして利用できるようになる。

loadとincludeは、モジュールとはあまり関係が無く、むしろモジュール以外のRubyの(静的または動的にロード可能な)ソースとバイナリに関係がある。
loadの処理は、実質的にファイルを読み込み、それをソースファイルの現在の位置に挿入し、ファイルの定義をその位置で利用できるようにする。
requireの処理はloadに似ているが、ファイルが既にロードされている場合はロードしない。

Mix-inのルール

  • クラス内とモジュール内に同名のメソッドが定義されている場合、クラスのメソッドが優先される
  • 複数のモジュールをインクルードした場合、同名のメソッドが複数定義されている可能性があるが、その場合は後からインクルードしたメソッドが優先される
  • モジュールが入れ子になっている場合、単純継承のように振る舞う
# Module M1を宣言
module M1
  def method
    puts "モジュールM1のメソッド"
  end
end

# Module M2を宣言 
module M2
  def method
    puts "モジュールM2のメソッド"
  end
end
 
# Module M3を宣言
module M3
  include M2 # Module M2をインクルード
end

# Class Cを宣言
class C
  def method
    puts "クラスCのメソッド"
  end
  
  # Module M1 M2 をインクルード
  include M1
  include M2
end

# Class Dを宣言 
class D
  # Module M1 M2 をインクルード
  include M1
  include M2
end
 
class E
  include M3
  include M1
end
 
p C.ancestors   # 単純継承のような動作をする
C.new.method    # 同名のメソッドはクラスのものが優先される
D.new.method    # 後からインクルードしたモジュールのメソッドが優先される
p E.ancestors   # 入れ子のモジュールも単純継承のような動作をする


contentsへ