This is the closest to what you had. I took the liberty of changing it to standard Ruby coding style, but notice that the only real change is the first line of add_hello_method_to_class_of:
class SomeClass; end
class AnotherClass; end
alpha = SomeClass.new
beta = AnotherClass.new
def add_hello_method_to_class_of(obj)
obj.class.send(:define_method, :hello) do
'Hello'
end
end
add_hello_method_to_class_of(alpha)
add_hello_method_to_class_of(beta)
gamma = AnotherClass.new
alpha.hello
beta.hello
gamma.hello
Originally, you had
def obj.class.hello
This will work, but it doesn't do what you think it does. This will add a singleton method to the class object itself, but it appears you assume that it will add an instance method. If you want to add an instance method, you need to use Module#define_method like this:
obj.class.define_method(:hello)
Except that Module#define_method is private, so you need to use reflection to circumvent that access restriction:
obj.class.send(:define_method, :hello)
Note that I also changed the name of the method from add_hello_method_to to add_hello_method_to_class_of, since, well it doesn't add the hello method to its argument, it adds it to its argument's class.
However, if you do monkey patching like this, it is generally considered good practice to use mixins instead, since then, the mixin shows up in the object's inheritance chain, which leaves anybody debugging that code at least a fighting chance to figure out where the heck that mysterious hello method is coming from:
# file: hello_extension.rb
module HelloExtension
def hello
'Hello'
end
end
def add_hello_method_to_class_of(obj)
obj.class.send(:include, HelloExtension)
end
# some other file
require 'hello_extension'
class SomeClass; end
class AnotherClass; end
alpha = SomeClass.new
beta = AnotherClass.new
add_hello_method_to_class_of(alpha)
add_hello_method_to_class_of(beta)
gamma = AnotherClass.new
alpha.hello
beta.hello
gamma.hello
Now, you can easily debug this code:
gamma.class.ancestors
# => [AnotherClass, HelloExtension, Object, Kernel, BasicObject]
If someone wonders where the hello method is coming from, then it doesn't take much to figure out that a mixin called HelloExtension probably has something to do with it. And following standard Ruby naming conventions they even know to look in a file named hello_extension.rb
You can even do this:
gamma.method(:hello).source_location
# => ['hello_extension.rb', 3]