【Ruby】モジュールのミックスインについて


はじめに

今回はRubyのモジュールについてまとめました!

モジュールには様々な用途があります。

主に以下のような用途です。

・クラスにインスタンスメソッドを追加する(ミックスイン)

・クラスにクラスメソッドを追加する(ミックスイン)

・クラス名などの重複を防ぐためにネームスペース(名前空間)を作成する

・ミックスインせずにモジュール単体としてメソッドを定義

など。

最初は何を言ってるか全くわけがわからないと思います。

全ての機能をここで説明するととても長文になってしまうので、今回は上記のうち上から2つ(ミックスイン)に関して説明します。


モジュールとは

ここで説明する”ミックスインの機能を持つモジュール”とは、そもそも何でしょうか。

説明する前に、まずクラスに関してざっとおさらいしておきます。

継承関係にあるクラスは、親クラスのメソッドを子クラスでも呼び出すことが出来ました。

以下がその例です。


test.rb

class User

def name(name)
conversation = "hello,#{name}"
end
end

class Person < User
end

person = Person.new
person.name("たろう")
#出力結果 ==>"hello,たろう"


親クラスがUserで、子クラスがPersonです。

class Person < UserでUserクラスを継承しています。

その為Personクラスのインスタンスに対して、Userクラスのnameメソッドを呼んだ際に、

ちゃんと"hello,たろう"と返っていることから親クラスのメソッドが使えていることがわかります。

このように、継承していれば、親クラスのメソッドは使用できるのですが、逆に

継承していなければ他クラスのメソッドは使用できないとも言えます。

継承関係にはしたくないけれども、他クラスと全く同じメソッドを使いたい!と言う場合。

継承できないから同じ内容を毎回毎回クラスごとに書かなくてはいけないんでしょうか?

確かにそれでも良いかもしれませんが、コードの量が増えますし、

理想的なコーディングとして重複した処理は避けるべきです。

こんな時に役立つのがまさに!モジュールのミックスイン機能です!!

簡単に説明すると、共通のメソッドをモジュール内に定義しておき、

それをそれぞれのクラスで呼び出して使用することができる機能です。

このモジュールを呼び出すことをミックスインと呼びます。


モジュールのミックスイン

ではさっそくモジュールのミックスインに関して解説します。

とりあえずモジュールの書き方に関して先に見ておいてください。以下のようになります!


test.rb

module モジュール名

#モジュールの内容(メソッドやクラスなど)
end

書き方はいたって簡単ですね。ではさっそく使い方を解説します!


include

まずはインスタンスメソッドをモジュール内に定義して継承関係ではない2つのクラスにそれぞれ適用するケースです。

module名Helloを最初に定義し、(#---①)

moduleを読み込むためにそれぞれのクラスでincludeします。

include モジュール名と書くだけで読み込むことができます。 (#---②)

Userクラス内のnameメソッド内でHelloモジュールのhelloメソッドを呼び出しています。(#---③)

同じくDogクラス内のnameメソッド内でもHelloモジュールのhelloメソッドを呼び出しています。(#---④)

その後、それぞれのクラスのインスタンスを作成し、nameメソッドを呼び出すと、ちゃんとnameメソッド内のhelloメソッドが呼び出されていることが確認できます。(#---⑤)


test.rb

module Hello   #---①

def hello(name)
puts "hello,#{name}"
end
end

class User
include Hello #---②
def name
hello("たろう")  #---③
end
end

class Dog
include Hello #---②
def name
hello("ぽち")  #---④
end
end

user = User.new
user.name
# 出力結果 ==>"hello,たろう" #--⑤

dog = Dog.new
dog.name
# 出力結果 ==>"hello,ぽち" #---⑤


※モジュールもクラスも今回同じファイル内に書いてしまっていますが、もちろん別々にファイルを分けて頂いてOKです!

このように、モジュールで共通のメソッドをひとまとめにすることで、異なるクラスでもモジュール内のインスタンスメソッドが使用できます。


extend

includeはインスタンスメソッドをモジュールから呼び出すために使用しましたが、クラスメソッドの呼び出しにはextendを使用します。

モジュールの定義方法はincludeの時と変わりません。


test.rb

module Hello

def hello(name)
puts "hello,#{name}"
end
end

class User
extend Hello
def self.name
hello("たろう")
end
end

User.name
# 出力結果 ==>"hello,たろう"


つまり、モジュール内のメソッドをインスタンスメソッドとして使用するのか、クラスメソッドとして使用するのかでincludeとexcludeどちらを使うかが決まると言うことですね。

モジュール内の記述は変わらないので、同じモジュール内のメソッドでもクラスによってはインスタンスメソッドあるいはクラスメソッドになりうると言うことですね!とても便利です!


さいごに

今回はモジュールの機能のうち、ミックスインに関して説明させて頂きました!

モジュールには他にも機能があるので、ぜひ気になる方は調べてみてください:relaxed:

【参考】

書籍 プロを目指すためのRuby入門(伊藤 淳一 著)