本記事ではモジュールとMix-inについて解説します。
モジュールとは何かを一言で表現すると「処理をまとめたもの」となります。
前記事で処理をまとめたものとしてクラスを解説しました。同時に、クラスは共通関数ではない!と解説しました。
一方、モジュールは共通関数に近いです。
では早速見てみましょう。
モジュールとは何か
モジュールとは前述のとおり処理をまとめたものです。
基本形は、ほぼクラスと同じです。
module モジュール名 # 処理 end
実際に定義してみる
名前を渡してあいさつを返すモジュールを定義してみましょう。
module SayhelloModule def sayhello(name) puts "こんにちは!" + name + "さん" end module_function :sayhello end
モジュールの中にsayhelloメソッドを宣言しました。引数を受け取り、その引数を間にはさんで「こんにちは!(引数)さん」と答えてくれます。
ただし、宣言するだけでは呼び出せません。外部から呼び出せるようにするために、module_functionを使います。
引数としてメソッド名をシンボルで渡します。
sayhelloを呼び出してみましょう。
SayhelloModule.sayhello("potepan")
[実行結果]
こんにちは!potepanさん
モジュール内のメソッドを呼び出せました。
また、以下のような書き方もできますので、覚えておくと良いでしょう。
module SayhelloModule def self.sayhello(name) puts "こんにちは!" + name + "さん" end end
module SayhelloModule def SayhelloModule.sayhello(name) puts "こんにちは!" + name + "さん" end end
モジュールの中にクラスや定数
先ほどの例では、モジュールの中にメソッドを定義しまいた。
メソッドだけでなく、定数やクラスを宣言することも可能です。
module SayhelloModule1 Const = 100 class Sayhello def sayhello puts "from sayhello1" end end end module SayhelloModule2 class Sayhello def sayhello puts "from sayhello2" end end end # クラスのインスタンス化(SayhelloModule1)とメソッド呼び出し sh1 = SayhelloModule1::Sayhello.new sh1.sayhello # 定数の呼び出し p SayhelloModule1::Const # クラスのインスタンス化(SayhelloModule2)とメソッド呼び出し sh2 = SayhelloModule2::Sayhello.new sh2.sayhello
[実行結果]
from sayhello1 100 from sayhello2
モジュール内の定数呼び出しと、クラスのインスタンス化まで確認できました。
名前空間
ここで1つ確認してください。
先ほどの2つのモジュールで、クラス名もメソッド名も同じなのはお気づきでしょうか?
SayhelloModule1の中、SayhelloModule2の中それぞれで別世界となっており、同じ名前をつけても衝突しません。
それぞれの世界を名前空間といいます。
世界が異なれば、同じ名前でも良いのです。
モジュールの特性
クラスと比較したときの、モジュールの特性をまとめました。
インスタンス化できない
モジュールはインスタンス化できません。つまり、以下のようなことはできません。
SayhelloModule.new
継承できない
あるモジュールとわずかに異なる仕様を持つモジュールを作りたいとします。
クラスであれば継承が使えます。微妙に異なる部分だけ子クラスで定義すればよいのです。
しかしモジュールでは、継承ができません。
以上のインスタンス化できない、継承できないという2つの「できない」があります。しかし、それを補って余りある特徴があります。
以降、解説します。
Mix-in
クラスにモジュールを取り込むことをMix-inといいます。
SayhelloClass3に、SayhelloModule3というモジュールをMix-inしてみましょう。
module SayhelloModule3 def SayhelloMethod3 puts "SayhelloMethod3" end end class SayhelloClass3 include SayhelloModule3 end sc3 = SayhelloClass3.new sc3.SayhelloMethod3
[実行結果]
SayhelloMethod3
SayhelloClass3の中身は、includeの1行のみですがキチンと動作しています。
このように、モジュールの中身をそのまま取り込んで、あたかも自クラスの1部分として使うことをMix-inといいます。
多重継承もどき
Rubyは、Javaなどと同じように多重継承を許していない言語です。
つまり2つの親クラスを同時に継承できないのです。
よって、1つのクラスを継承してしまった後、変更を加えるには子クラスに手を加えるしかありません。
ところがMix-inを使うと、あたかも親クラスのように振る舞うことができるのです。
また1度モジュールを定義すれば、他のクラスでも使えるのでとても便利です。
インスタンスにメソッド追加
moduleは、すでに生成されたオブジェクトに後から追加することもできます。
module SayhelloModule3 def SayhelloMethod3 puts "SayhelloMethod3" end end obj = Object.new # サンプルなので中身は特に指定しません obj.extend SayhelloModule3 obj.SayhelloMethod3
[実行結果]
SayhelloMethod3
すでにできあがったobjに、extendというキーワードを使ってSayhelloModule3を追加できました。
まとめ
本記事では、モジュールとMix-inを解説しました。
クラスとモジュールのちがいや特性をおさえ、効率的なプログラミングができるようがんばってみてくださいね!