rubyのmoduleメソッドの呼び出し方法

Rubyの module は慣れ親しんできたVB.NETのModuleとは 大分違うようなので整理しておこうと思います。

moduleのメソッドは関数として使えない

Rubyのmoduleのメソッドは普通に定義しただけじゃ、関数として使えない。

module ModTest
  def sayHello
    puts "こんにちは"
  end
end
# sayHelloをmoduleの外から実行すると・・
ModTest::sayHello()
#=> undefined method `sayHello' for ModTest:Module (NoMethodError)
# 呼び出せない・・

moduleのメソッドを呼ぶ方法

moduleのメソッドを呼ぶには、以下の3つの方法がある。

1. mixinを使う

別にclassを定義して、呼び出したい関数を含むmoduleをincludeする。 これがRubyで最も一般的なやり方らしい。 コードにするとこんな感じ。

class ClsTest
  include ModTest
  # ModTestをmixinします
end
# インスタンスを作ってincludeしたmoduleのメソッドを呼び出す
cls = ClsTest.new
cls.sayHello
#=> こんにちは

2. module_functionを使う

module_functionで関数として使いたいメソッドが指定できる。

module ModTest
  def sayHello
    puts "こんにちは"
  end
  # 外部から関数として使いたいメソッドを指定します。
  module_function :sayHello
end
# sayHelloをmoduleの外から実行すると・・
ModTest::sayHello()
#=> こんにちは

module_functionを実行すると以下の2つの処理が行われる。  ・インスタンスメソッドのprivate化  ・publicクラスメソッドの作成

なので、mixinでmodudleを取り込んだクラスから呼び出す為には、 スコープを public に戻してやる必要がある。

module ModTest
  def sayHello
    puts "こんにちは"
  end
  module_function :sayHello
    # module_functionを使うとインスタンスメソッドがprivate化されてしまうので、
    # mixinでも使う場合は public に戻してやる。
  public :sayHello
end

class ClsTest
  include ModTest
end

cls = ClsTest.new
cls.sayHello
#=> こんにちは

ただ、こういうふうに無理やりスコープを Public に戻すのが 正しいのかわからないので、とりあえずこれは使わないようにする。

3. クラスメソッドとして宣言する

ModuleもClassなので、当然クラスメソッドを定義できます。 だから、Classのクラスメソッドと同じようにこんな感じで定義可能です。

module ModTest
  class << self
    def sayHello
      puts "こんにちは"
    end
  end
end

ModTest::sayHello

簡単ですね。

まとめ

VB.NETにおける Module は関数定義を集めたもので、 ユーティリティ関数をまとめておくような使い方が一般的でした。 しかし、Rubyの module は主にクラス拡張の手段という感じですね。 だから、ここに書いた 2(module_functionを使う方法) や 3(クラスメソッドとして宣言する) 方法はあまり使うべきではないのかもしれませんね。。