Rubyのモジュールとクラスの違いについて。モジュールの中のメソッドの呼び出し方実例と注意点。
##目次
- モジュールとは?
-
モジュールのメリット
3. メリット1 複数継承可能
4. メリット2 同じメソッド名を定義できる -
モジュールの呼び出し方法
6. classの中で読み込む
7. moduleの中でmodule_functonを定義する
8. Objectとextendを使う
9. NG事例 - mixinとは?
##モジュールとは?
- メソッドを記述しておく場所
- moduleの中にdefでメソッドを書いていく
- メソッドを複数定義できる
module <モジュール名>
def <メソッド名1>
処理1
end
def <メソッド名2>
処理2
end
,
,
,
end
##モジュールのメリット
- 複数読み込み可能
- 同じメソッド名を定義できる
###メリット1 複数継承可能
複数のクラスを継承したい(メソッドの書かれた複数のファイルを読み込みたい)場合の代替手段。
▼どういうこと?
Rubyのデメリットとして、クラスを一つしか継承できない(単一継承)がある。
このため、他のクラスを読み込んで、更に既に定義したメソッドを読み込みたい場合に、他のクラスを読み込むことができない。
この解決手段としてモジュールがある。モジュールを使えば、継承するクラスの他にもメソッドを読み込むことができるようになる。
###メリット2 同じメソッド名を定義できる module自体の名前が異なれば、同じメソッドでも違う名前になる。(オブジェクトのKVと同じ。)
obj1 = {name: yamada, age: 24}
obj2 = {name: tanaka, age: 24}
#呼び出し
obj1.name #yamada
obj2.name #tanaka
nameという同じプロパティ名が存在するが、大元がobj1とobg2で異なるため、違う扱いになる。
▼モジュールの場合
module Aaa
def hello
p "こんにちは"
end
end
module Bbb
def hello
p "ニーハオ"
end
end
メソッド名はどちらもhelloだが、入れ物が異なるので問題ない。
##モジュールの呼び出し方法 モジュールの呼び出し方法は2つ。
- classの中で読み込む
- moduleの中でmodule_functonを定義する
- Objectとextendを使う
###1. classの中で読み込む
・include <モジュール名>
で読み込む
・<クラス名>.new.<メソッド名>
で実行する
メソッドの実行方法は、通常のクラスと同じくインスタンスを作成して、メソッドを呼び出す。
#モジュールの定義
module Aaa
def hello
p "こんにちは"
end
end
#クラスで読み込み
class Xxx
include Aaa
end
#メソッドの実行
Xxx.new.hello
=> "こんにちは"
####モジュールが複数ある場合
カンマで繋ぐ。
・include <モジュール名1>, <モジュール名1>,,,
▼注意点
メソッド名が同じ場合は、上のモジュールのメソッドが読み込まれる。(下側は無視される)
#モジュールの定義
module Aaa
def hello
p "こんにちは"
end
end
module Bbb
def hello
p "ニーハオ"
end
end
#クラスで読み込み
class Xxx
include Bbb, Aaa
end
#メソッドの実行
Xxx.new.hello
=> "こんにちは"
###mixinとは?
クラスの中でmoduleを呼び出すことをmixin(ミクシン)と呼ぶ。
mixinというメソッドがあるわけではなく、classの中でincludeを使ってmoduleを呼び出すこと = mixinとなる。
<
を継承と呼ぶのと同じく、ただの名称。
###2. moduleの中でmodule_functonを定義する
・module_function :<メソッド名>
▼注意点
-
:
の後にスペースを空けない(エラーになる) - 記述するメソッドは一つずつ。(メソッドが複数ある場合は複数記述する。カンマでつなげない)
#モジュールの定義
module Aaa
def hello
p "こんにちは"
end
module_function:hello
end
#メソッドの実行
Aaa.hello
=> "こんにちは"
###3. Objectとextendを使う `Object.new`で空のオブジェクトを生成し、`.extend <モジュール名>`で拡張すれば、メソッドが使用できる。
#モジュールの定義
module Aaa
def hello
p "こんにちは"
end
end
#オブジェクトの生成
obj = Object.new
#モジュールの拡張
obj.extend Aaa
#メソッドの呼び出し
obj.hello
=> "こんにちは"
###NG事例 モジュールはクラスの中で定義した関数のように、`<モジュール名>.new.<メソッド名>`では呼び出せない。
#モジュールの定義
module Aaa
def hello
p "こんにちは"
end
end
#メソッドの実行
Aaa.new.hello
#エラー内容
NoMethodError (undefined method `hello' for Aaa:Module)