読者です 読者をやめる 読者になる 読者になる

Ruby でオブジェクトのメソッド呼び出しをフックする方法

Ruby エキスパートな人には特に新しい話は無いですが、何か抜けている所などありましたらツッコミいただけたら幸いです。

オブジェクトをすりかえる方法

Ruby でオブジェクトのメソッド呼び出しをフックする方法としてまず考えられるのは、method_missing を使う方法です。
メソッドが定義されていない名前でメソッド呼び出しがあると、Ruby では method_missing というメソッドが呼ばれるので、メソッドを何も定義していないクラスを作り、目的のオブジェクトを、そのクラスのインスタンスとすりかえます。そして、method_missing の中から、__send__ で本来のメソッドを呼びます。サンプルを示します。

ruby 2.0 以降では BasicObject という、ほぼ本当に空っぽのクラスがあるのですが、少々特殊過ぎて癖があるクラスですので、サンプルでは使っていません。

オブジェクトの extend を使う方法

元のオブジェクトを拡張して機能を追加する方法としては、『メタプログラミングRuby』などでは alias を使って元のメソッドに別名を付けて、同名のメソッドを再定義し、その中から別名で呼ぶ、という方法が紹介されており、Ruby コミュニティでも一定の支持がある方法かと思います。が、問題もあります( るびきちさんの d:id:rubikitch:20080504:1209835550 を参照)。
ここでは、るびきちさんが紹介されている最後の方式に、さらにイントロスペクションを使ってメソッドを列挙して追加するサンプルを示します。

「__なんとか__」という名前のメソッドには手をつけないようにしています。また define_method で定義されているメソッドからは、引数なしの super で、引数が自動的に引き継がれる機能が使えませんので、自分で引数のひきまわしをしています。