I’m just exploring ruby and was wondering about the theoretical possibility of adding a method to the class of an object. For example, define a method that takes in a parameter and would add a method to the class of that parameter (not just to the parameter object itself). Something like this example:
class SomeClass
end
class AnotherClass
end
alpha = SomeClass.new
beta = AnotherClass.new
def AddHelloMethodTo param
# This is where I'm trying to
# add a method to the class of the parameter
def param.class.Hello
"Hello"
end
end
AddHelloMethodTo alpha
AddHelloMethodTo beta
gamma = AnotherClass.new
alpha.Hello
beta.Hello
gamma.Hello
(Excuse me if I have syntax errors / typos I’m REALLY new to this!)
Notice how I don’t call the AddHelloMethodTo on gamma but I expect Hello to be defined because I added it to the class.
Is this possible?
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:Originally, you had
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_methodlike this:Except that
Module#define_methodisprivate, so you need to use reflection to circumvent that access restriction:Note that I also changed the name of the method from
add_hello_method_totoadd_hello_method_to_class_of, since, well it doesn’t add thehellomethod 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
hellomethod is coming from:Now, you can easily debug this code:
If someone wonders where the
hellomethod is coming from, then it doesn’t take much to figure out that a mixin calledHelloExtensionprobably has something to do with it. And following standard Ruby naming conventions they even know to look in a file namedhello_extension.rbYou can even do this: