What will be the output of the following code?
The output is as follows:
Decorator#to_s method, which is (unsuccessfully) trying to override
String#to_s, will be defined in the singleton class of an instance of the
Decorator class, upon instantiation. However, when the
Decorator#initialize method gets called during the instantiation, the code there actually reopens the singleton class on the instance and adds/overrides methods in it.
In order to override the
String#to_s method, the only way is to reopen the instance’s singleton class, some time after the
Decorator#initialize call. It is the only way because the singleton class is the very first level at which the method lookup algorithm searches. Here is one implementation:
Which will produce this output:
my string overridden!
While this works, that would not be the recommended way to add or alter the behavior on a class (or even on a specific instance). Jay Fields explains why you should use modules instead of the metaclass. Note: Fields’ “metaclass” is what I called “singleton class” in my post, in an attempt to stick with the definitions introduced in the PickAxe.