In this post I’m focusing on chapter 13: Get the Behavior You Need with Singleton and Class Methods. This chapter was a nice wow moment for me, but also a bit embarrassing as this isn’t really advanced Ruby knowledge but I’ve managed to never really learn it. So what does the chapter talk about? It talks about Ruby singleton and class methods and that they’re basically the same thing under the hood!
So we all know that we can define class methods like this:
1 2 3 4 5
And we also know that this is equivalent to the following:
1 2 3 4 5 6
Now let’s compare this to defining a method on an object instead of a class (aka defining a singleton method):
1 2 3 4
Quite similar that code, isn’t it? This could just be a coincidence, but of course being a nicely designed language it isn’t.
So how does it work?
Quite easily actually. As you know Ruby is an object oriented language down to it’s core. So it comes naturally that classes are just objects, too. So when you are defining class methods you are actually defining singleton methods on the instance of Class that defines your class (DennisMoore in this case) which is no different from defining singleton methods on “normal” objects!
And where are those methods stored?
Now that we know that we are just defining singleton methods the only question remaining is where these methods are stored? Remember, when we are calling a method on an object, Ruby searches for the method in the class of the object, then the super class and so on until it finds it. But of course we can’t put our singleton methods into the class as we only want these methods to be defined for that single object. So we could come up with some hack that stores the methods somehow in the instance. Or, we could do the elegant thing and add a special class to each object that sits between it and the “real” class of that object. This way we can use the normal rules of inheritance for singleton methods. This is of course what Ruby does. It calls it the singleton class even.
So to summarize: Each Ruby object has a singleton class in the method lookup path between itself and its class. That’s where singleton methods are defined. And class methods are just a special case of this as classes themselves are just objects (and instances of class Class).