CTC 教育サービス
[IT研修]注目キーワード Python UiPath(RPA) 最新技術動向 Microsoft Azure Docker Kubernetes
みなさん、こんにちは。
今回は前回ご紹介していた「モジュール」についての続きです。
Rubyのモジュールには、主に3つの役割があるといえます。
① 共通に利用するAPI的な関数(モジュール関数)の提供
② 継承に代わってクラスに実装を提供
③ 名前空間の提供
このうち、①と②について前回ご紹介しました。
今回は、そのモジュール定義において、メソッドをモジュール関数として定義(module_functionで指定)した場合と、普通のメソッドとして定義した場合での挙動の違いについてご紹介したいと思います。
前回の②のパターンでは、クラスがincludeメソッドでモジュールの実装を提供されると、クラスのpublicメソッドのように外部から利用することが可能でした。
(以下のプログラムは前回の再掲です)
では、もしモジュール内のメソッドがモジュール関数だった場合、includeされた場合の挙動はどうなるのでしょうか。以下のコードでは、モジュールFooModuleのメソッドbarはmodule_functionメソッドによってモジュール関数として定義されています。BazClassではこのモジュールの実装がincludeメソッドで提供されています。さらに、BazClassのメソッドbazMethodでは、モジュール関数barを呼び出しています。
このコードを、module2.rbというファイルに保存して実行した結果は、以下のようになります。
bazMethod内でモジュール関数を実行しても、問題なく呼び出すことができました。しかしながら、クラスの外から直接モジュール関数を実行しようとすると例外となりました。これは、どういうことなのでしょうか。
モジュール関数は文字通りモジュールに結び付く関数であり、モジュールに対して直接呼び出す共通APIのような役割を持っているため、呼び出し方を統一したい=モジュール以外からの呼び出しをさせないようにしたい、という意図があるのかと思われます。そのため、クラスにincludeしたときには、モジュール関数はprivate扱いとなり、クラスの外部から呼びだすことができなくなります。
一方で、非モジュール関数(module_functionで指定されていないモジュール内のメソッド)は、モジュール関数としては扱えない(モジュールに対して直接呼び出せない)かわりに、includeされたクラスのpublicメソッドとして外部からの呼び出しが可能になります。この特徴を利用すると、継承に代わってクラスに実装を提供することが可能となります。
モジュールには様々な役割が持たされているため、どのようにメソッドを扱わせたいか(共通API的なメソッドにしたいのか、継承以外のクラスに対する実装の提供手段にしたいのか)を、その意図に合わせてコントロールできるようになっているのですね。
これらの関係を表にまとめると以下のようになります。
モジュール内のメソッド定義による挙動の違い
なんだか、もうこれだけでお腹いっぱいな気もしてきましたね・・・。モジュールについての話題は2回分くらいでお話しできると思っていたのですが、なんだかちょっと長くなりそうなので、名前空間についてのお話はまた次回にさせていただきたいと思います。ついつい話過ぎてしまう、私の研修の講義のようになってしまいました(なるべくそうならないように気をつけてはいるのですが・・・)。
ということで、今回もいったんここまでです。次回の「Rubyのモジュールについて(3)」もどうぞお楽しみに。
[IT研修]注目キーワード Python UiPath(RPA) 最新技術動向 Microsoft Azure Docker Kubernetes