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(クラスメソッドとして宣言する) 方法はあまり使うべきではないのかもしれませんね。。
2、3に書いた方法でstatic method化することよくあるとコメントでご指摘頂きました。。
(ただし、module_function化したものを再度Publicにするのは駄目だろうという指摘も。気をつけます。)