Rubyでメソッドを上書き(monkey patch)をする方法を調べてみた

Gemを作っていた時に、どうしても依存しているGemの挙動を変える必要があったので、どういう方法があるのか調べてみた。

継承 + Mixin

まず、普通にmoduleを作成して、classをオープンしてincludeする。もちろん

Rubyのクラス継承チェインの上位に上書きしたいmoduleが来てしまうため無理。

クラス継承

普通にクラスを継承して、上書き。

オープンクラス + alias_method

extendしていることを明確にするためにmoduleをincludeする形にしたが、classをopenして、alias_methodを使うのと同じで、想定通りの挙動になる。

delegation(委譲)

継承やオープンクラスをしないで、メソッドの実行を委譲することもできるっぽい。

DelegateClass(Country)でCountryオブジェクトにインスタンスメソッドを委譲するクラスが定義され、そのクラスを継承した DelegateCountry クラスを定義することでメソッド実行を委譲している。

レシーバーを動的に紐付ける

クラスのインスタンスメソッドを元にUnboundMethodオブジェクトを作成して、
bindをつかってレシーバーと紐づける。

これも、継承やオープンクラスをしないでできそう。

クラス継承チェインの先頭に追加する

includeした場合は、継承チェインの上位に挿入されるので上書きできないけど、prependを使うと
継承チェインの先頭に追加されるので、上書きできる。

と、ほかにもいろいろとやり方はありそうだった。

結局、今回はalias使う方法にした。。。

参考にしたページ: When monkey patching a method, can you call the overridden method from the new implementation?

Comments