Discussion About Open Classes and Monkey Patching at #retroruby
While at RetroRuby 2014 a very good question was asked in the newbie track. The following code sample had just been shown on some basic awesomeness of Ruby:
One of the participants then asked why that worked but the inverse didn’t:
Oops what just happened?
In Ruby, virtually everything is accomplished by sending a message to another object. Above we would say:
Send the message
Send the message
“Sending a message” is the Java equivalent of calling a method. Another way to write the above is:
Here we used the normal “method” calling syntax:
You’ll also probably see the following:
This time we explicitly sent the message:
doesn’t check if the message you passed was supposed to be public or private.
Generally, what you wanted to do was dynamically send the message while still
making sure to respect the public API of the object. To do this you should use
So back to the original issue. Both
Fixnum respond to the message
String’s implementation knows what to do when the argument is a
Fixnum. When we reverse it, the
Fixnum implementation doesn’t understand
what to do with a
How to fix this?
Well you probably shouldn’t. But just for fun we’ll use Ruby’s open class
behavior to monkey patch
1 2 3 4 5 6 7 8 9 10 11
It worked!! Before you go doing this to everything, be aware we’ve now lost the
ability to do normal multiplication. Additionally, we’ll overflow the stack
trying to multiply two
In Ruby, most things are messages sent from one object to another. Some times the language gives a little extra syntactic sugar to make sending the message more readable.
Additionally, open classes and monkey patching have their uses. Just be aware that with great power comes great responsibility. Always stop to ask yourself if this is really a good idea; and try to never change existing behavior if you can.
So what if we just wanted to extend the existing functionality. There are a lot of ways to do this and covering each, along with the pros and cons is very out of scope for this post. I’m just going to demonstrate one way to illustrate how it could be done.
You’ll need a new irb or Pry session so we get the original implementation for
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17