5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Rubyのモジュール関数がややこしいのでgemを作った

Posted at

別件でGemを自作している過程で、モジュール関数のハンドリングがややこしいことに気づいてしまったので、それをすっきりさせようとGemを作ってしまいました。

モジュール関数とは

Rubyのメソッドは「public/private/protected」や「インスタンスメソッド/クラスメソッド/特異メソッド」というように区分できますが、「モジュール関数」は、これらの区分とは大きく異なってくるものです。

というのも、「モジュール関数」は単体のメソッドを指す語ではなく、

  • モジュールのprivateなインスタンスメソッド
  • モジュールのpublicな特異メソッド

という、同じ名前・動作の2つのメソッドが存在するときに、そのセットを指す語、ということです。

このように2つ定義することで、Math.sinのようにモジュールから呼ぶ、あるいはinclude Mathとすればsinだけで使える、というような利便性を持つことになります。

ハンドリングの複雑さ

「モジュール関数」が2つのメソッドのセットから成っているので、操作を加えようとすれば何かと厄介なことになります。たとえば、aliasでメソッドのコピーをしようとすると、privateなインスタンスメソッドだけコピーされますし、あるモジュールで定義されたモジュール関数を別なモジュールに持って行って、そちらのモジュール関数としようとしても一筋縄では行きません。

Gem化してみた

ということで、このあたりのハンドリングを担うGemとして、jkr2255/function_moduleを作ってみました。これには3つの機能があります。

Module#module_functions

引数なしのpublicメソッドで、privateインスタンスメソッドとpublic特異メソッドの両方で定義されているメソッド(≒モジュール関数)の一覧を返します。なお、Module自体やその先祖で定義されたメソッドは除外しています。

Module#include_module_functions(mod)

別なモジュール内でinclude SomeModuleの代わりにinclude_module_functions SomeModuleとすると、通常のincludeに加えて、SomeModule内のモジュール関数を、include先の特異メソッドとしても使えるように処理してくれます。

Module#alias_module_function(new_name, old_name)

alias_methodの代わりにこれを使うと、privateインスタンスメソッドのコピーだけでなく、特異メソッドの方もコピーします。

5
4
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?