On 20/06/2012, at 5:34 AM, Iain Barnett wrote:

> 
> Any thoughts or suggestions would be appreciated.


I don't have a problem with re-opening classes either. It's a tool in the Ruby tool box so why not use it. Especially when, as you pointed out, inheritance sometimes doesn't do what you'd expect. Some Ruby base classes don't call initialize which can be a problem.

Personally when I monkey patch I put my new methods in a module and then include them in the target class. 

module MyStringExtensions
    def foo
        "bar"
    end
end

class String
    include MyStringExtensions
end


This has three benefits;
1. Reuse. You can include the same monkey patch in different classes. This almost never happens :)
2. Visibility. If you ask for the ancestors of the base class you will see your module in the list which will give users a clue why the class isn't behaving in a standard way and a pointer to where they should start looking.

String.ancestors
 => [String, MyStringExtensions, Comparable, Object, Kernel, BasicObject] 

3. Targeted extension. Using extend you can apply your monkey to specific objects rather than every object of that type in the system. Though, as @Bartosz pointed out, this may cause performance degradation's.

a = "asdfghj"                                           # => "asdfghj" 
b = "2345678"                                        # => "2345678" 
b.extend MyStringExtensions
a.foo                                                         # NoMethodError: undefined method `foo' for "asdfghj":String
b.foo                                                        #  => "bar" 



Henry