[ruby]Module/Mix-in/include/prependについて
自己学習でrubyのModule(モジュール)について調べることがあったので、自分なりに学習したことをまとめました。よかったら参考にしてみてください。
Module(モジュール)
クラスと同じようにメソッドを定義することができ、処理の部分をまとめたもの。
特徴
①モジュールでインスタンスを持つことはできない。
②モジュールは継承することができない。
(ただし、Mix-inというモジュールで定義したメソッドをクラスに取り込み、モジュールのメソッドを取り込んだクラスのインスタンスに対して使用することができます。)
また、モジュール内のメソッドを実行するときは、メソッドをモジュール関数として外部に公開するため、module_function: メソッド名で指定し、「モジュール名.メソッド名」で実行となります。
https://qiita.com/shiopon01/items/fd6803f792398c5219cd
クラス内でモジュールを呼ぶときは「include」「prepend」メソッドを使用し、モジュールに含まれる定数やメソッドをクラス内で使用することができます。
https://www.sejuku.net/blog/16057
モジュールの使用例
module Hello
def hello
puts "こんにちは!"
end
module_function :hello
end
module Goodbye
def goodbye
puts "じゃあね〜"
end
module_function :goodbye
end
# 実行するときは、「モジュール名.メソッド名」で実行する
Hello.hello # => こんにちは!
Goodbye.goodbye # => じゃあね〜
module Hello
def hello
puts "こんにちは!"
end
end
module Goodbye
def goodbye
puts "じゃあね〜"
end
end
class Greeting
include Hello
include Goodbye
end
# Grretingのインスタンスを作成し、各モジュールを実行
greeting = Greeting.new
greeting.hello # => こんにちは!
greeting.goodbye # => じゃあね〜
module M
def greeting(name)
super
puts "#{name}さん、おはよう!今日も良い天気ですね〜"
end
end
module MM
def goodbye(name)
puts "#{name}さん、さようなら〜"
end
end
class A
prepend M
include MM
def greeting(name)
puts "#{name}さん、こんばんは!今日は寒いですね〜"
end
end
a = A.new
a.greeting("田中")
# =>田中さん、こんばんは!今日は寒いですね〜
# => 田中さん、おはよう!今日も良い天気ですね〜
a.goodbye("花子")
# => 花子さん、さようなら〜
Mix-in
クラスとモジュールを混ぜ合わせることで、多重継承の代わりに用いられます。
クラス内で「include モジュール名」と記述することで、モジュールで定義したメソッドをそのクラスに対して使用することができます。
(クラスで定義したインスタンスメソッドのように使用することができます。)
module M
def self_introduction(name, age)
"私の名前は#{name}です。年齢は#{age}歳。拳で!!!"
end
end
class A
include M
end
# クラスAのインスタンスを作成
a = A.new
# モジュールMのself_introductionメソッドを実行(モジュールMを取り込むことで、モジュールMで定義したメソッドをクラスAのインスタンスメソッドのように使用することができる。)
p a.self_introduction("織田信長", 21) # => "私の名前は織田信長です。年齢は21歳。拳で!!!"
# クラスAにモジュールMが含まれているか確認
p A.include?(M) # => true
Mix-inを実現するには、includeの他にもprependメソッドもあります。
prependはすでにあるクラスの動作を変更したいときに使用します。
includeとの違いは、モジュールとクラスに同じメソッド名があったときに、includeだとクラスの中にあるメソッドをよび、prependだとモジュールの中にあるメソッドを呼ぶことができます。
prepend 参考
https://docs.ruby-lang.org/ja/latest/method/Module/i/prepend.html
https://magazine.techacademy.jp/magazine/19880
includeでモジュールMをクラスAに取り込んだとき
module M
def greeting(name)
puts "#{name}さん、おはよう!今日も良い天気ですね〜"
end
end
class A
include M
def greeting(name)
puts "#{name}さん、こんばんは!今日は寒いですね〜"
end
end
a = A.new
a.greeting("田中") # => 田中さん、こんばんは!今日は寒いですね〜
prependでモジュールMをクラスAに取り込んだとき
module M
def greeting(name)
puts "#{name}さん、おはよう!今日も良い天気ですね〜"
end
end
class A
prepend M
def greeting(name)
puts "#{name}さん、こんばんは!今日は寒いですね〜"
end
end
a = A.new
a.greeting("田中") # => 田中さん、おはよう!今日も良い天気ですね〜
また、モジュールMの中で「super(オーバーライドしているメソッドを呼び出すもの)」を使用すると、クラスAのメソッドを呼び出すことができます。
module M
def greeting(name)
super
puts "#{name}さん、おはよう!今日も良い天気ですね〜"
end
end
class A
prepend M
def greeting(name)
puts "#{name}さん、こんばんは!今日は寒いですね〜"
end
end
a = A.new
a.greeting("田中")
# => 田中さん、こんばんは!今日は寒いですね〜
# => 田中さん、おはよう!今日も良い天気ですね〜
Discussion