※この記事は https://kunosu.qrunch.io/entries/QmFLXo16Vx9DyWrL に移動しました。
経緯
『オブジェクト指向設計実践ガイド』を読んで、
オブジェクトを生成するためのモジュール(=ファクトリー)を実際に書いてみました。
しかし、モジュール名.メソッド名
の形で呼び出すにはメソッドを外部に公開する必要があり、
その方法が調べると2つありました。
- メソッドの宣言時、メソッド名に
self
を追加する -
module_function :メソッド名
をモジュールに追加する
本ではself
をつけていたのでそちらで書きましたが、
上記2つの違いについては分からなかったのでコードを実行して調べてみました。
この記事で書いたソースコードは下記の Gist で公開しています。
https://gist.github.com/kunosu/7d51967d1a79815aadf0f32dadb50d69
実験用のモジュール
以下のようなモジュールに対して、普通に呼び出す、include
, extend
したクラスに対してメソッドを呼び出してみます。
Rubyは ver 2.5です。
Test_module.rb
module Test_module
def normal_method
# __method__ は実行中のメソッド名を文字列で返す
puts "called #{__method__}"
end
def self.self_method
puts "called #{__method__}"
end
def module_function_method
puts "called #{__method__}"
end
module_function :module_function_method
end
試してみた結果
呼び出し方法 | なし | self | module_function |
---|---|---|---|
Test_module.メソッド名 | × | ○ | ○ |
Test_module.rb
Test_module.normal_method
# => NoMethodError
Test_module.self_method
# => called self_method
Test_module.module_function_method
# => called module_function_method
モジュールをクラスに include
した場合
呼び出し方法 | なし | self | module_function |
---|---|---|---|
Test_class.メソッド名 | × | × | × |
obj.メソッド名 | ○ | × | × |
obj.メソッドを呼び出すメソッド | ○ | × | ○ |
Test_class_include.rb
require_relative "Test_module.rb"
class Test_class
include Test_module
def caller_normal_method
normal_method
end
def caller_self_method
self_method
end
def caller_module_function_method
module_function_method
end
end
Test_class.normal_method
# => NoMethodError
Test_class.self_method
# => NoMethodError
Test_class.module_function_method
# => NoMethodError
test_class = Test_class.new
test_class.normal_method
# => called normal_method
test_class.self_method
# => NoMethodError
test_class.module_function_method
# => NoMethodError
test_class.caller_normal_method
# => called normal_method
test_class.caller_self_method
# => NameError
test_class.caller_module_function_method
# => called module_function_method
モジュールをクラスに extend
した場合
呼び出し方法 | なし | self | module_function |
---|---|---|---|
Test_class.メソッド名 | ○ | × | × |
obj.メソッド名 | × | × | × |
obj.メソッドを呼び出すメソッド | × | × | × |
Test_class_extend.rb
require_relative "Test_module.rb"
class Test_class
extend Test_module
def caller_normal_method
normal_method
end
def caller_self_method
self_method
end
def caller_module_function_method
module_function_method
end
end
Test_class.normal_method
# => called normal_method
Test_class.self_method
# => NoMethodError
Test_class.module_function_method
# => NoMethodError
test_class = Test_class.new
test_class.normal_method
# => NoMethodError
test_class.self_method
# => NoMethodError
test_class.module_function_method
# => NoMethodError
test_class.caller_normal_method
# => NameError
test_class.caller_self_method
# => NoMethodError
test_class.caller_module_function_method
# => NoMethodError
試してみた結果からの self
と module_function
の使い分け
※試してみた結果から得たものであり、こう使うのが正しいという訳ではありません。
- モジュールだけで使う場合はどちらでもいい
- 書くのが楽なので
self
を使う - ファクトリーなど
- 書くのが楽なので
-
クラス名.メソッド名
の形で呼び出す場合は、メソッドに何も指定せず、extend
して使う- 特異メソッドとして使う
-
obj.メソッド名
の形で呼び出す場合は、メソッドに何も指定しない -
obj.メソッドを呼び出すメソッド
の形で呼び出す場合は、次のどちらかでextend
して使う- メソッドに何も指定しない
-
module_function
を使う
...結論としては、基本的にはself
を使えばいいのかな?