Module#refine を使って、クラス内だけでモンキーパッチすることができます。これでかなり安全だと思います。この例だと、クラス A の中で String のモンキーパッチをやっていますが、これはモジュールの外の名前空間を汚染しません。
自分だけで使うプログラムでは、積極的にモンキーパッチを使ったやり方が好きです。オープンクラスはいかにも Ruby らしい。ただ、他人も使うモジュールなどでは、モンキーパッチによりメソッドがバッティングするかも知れないので、こういうやり方だと「安全」だというわけです。しかし、リスクを負いつつ動的にプログラミングをするというのが Ruby 流なので、Rails みたいな有名なフレームワークだと、名前空間の「汚染」は却って生産的なのでしょうが(Rails よくシラネ)。
class A module ExString refine String do def print_out puts self end end end using ExString def b "inner".print_out end end A.new.b #=>"inner" "outer".print_out #=>a.rb:17:in `<main>': undefined method `print_out' for "outer":String (NoMethodError) using A::ExString "outer".print_out #=>"outer"
しかし、ここで
"outer".b
と意味のわからぬことをすると、NoMethodError がでません。というか、ただ "outer" が返されます。という仕様がよくわからない(Ruby 2.2.3)。バグじゃないの?*1
クラスの中にモジュールを入れるのは、以下のような場合があるため。こうしないと、A.new.b
の挙動が変ってしまう可能性がある。
module ExString refine String do def print_out puts self end end end class A using ExString def b "inner".print_out end end A.new.b #=>"inner" module ExString refine String do def print_out puts "test" end end end A.new.b #=>"test"