blog.waterlow.work

Ruby, Rails, js, etc...

【Ruby】Goldリベンジ今度こそ3-Module復習

モジュールの役割は

  1. 名前空間
  2. インスタンスメソッドの提供
  3. 特異メソッドの提供
  4. モジュール関数の定義

の4つ。クラスとの違いは

  1. インスタンス作れない
  2. 継承できない

の2つ。
サンプルコードです。

module M
  A = 1
end
module N
  A = 2
end
p M.class # Module
p M.ancestors # [M]
p M::A #1
class A
  include M
  include N
end
p A.ancestors #[A, N, M, Object, Kernel, BasicObject]
module M; end #モジュールとして再オープン
class M; end #クラスではないためエラー

ancestorsメソッドの実行するとincludeしたクラスの親クラスのように表示されますが実際はモジュールの機能をラップしたクラスが継承の列に組み込まれています。

名前空間の働きとしては(理解すれば自然だけど)やや独特。

module M
  A = 1
end
module N
  A = 2
end
TOP = "TOP"
class A
  include M
  include N
  p A #2
  p TOP #TOP
  p ::TOP #TOP
end
p A::M::A #1
p A::A #2

クラスを継承したら(moduleも最終的にクラスの継承に落とされるので)内部の定数を自分の中の定数として使えます。1つめのTOPはトップレベルはObjectクラスに属するのでそれを継承したクラスでも呼べるよ、という意味。2つめのTOPはトップレベルに定義された定数の独特の呼び方です。

あと脇道にそれてみました。こんなのもできます。

module M
  A = 1
  def m
    p 2222
  end
end
module N
  A = 2
end
TOP = "TOP"
class A
  class << self
    class << self
      extend M
    end
  end
end
A.singleton_class.singleton_class.m #2222

なんでもありなんですね。特異クラスを開くということすらただの定義式でしかないということです。これでわたしもメタプログラマー!!