2008-07-08

Metaclasses in Ruby

Well, I don't have any drawings of cartoon characters for you, but I do feel like making a post about Ruby.

I've been learning the Ruby programming language as I use it in some projects. So far, it's been a breath of fresh air after the rigidity of C++. Although C++ is very powerful, it can be kind of clumsy. I've been using a mixed approach in some projects, where Ruby code invokes C code.

Recently, I found myself playing in the deep end of the language. Every programming language has a deep end, whether or not it's advertised as a feature. With Ruby, the really hard part seems to be understanding the singletons.

Every object has a singleton which holds methods specific to that object. So the singleton can be viewed as sitting in between an object and its class. This is how you can add methods to an individual object.

In other words:
class C; def foo; puts "hi"; end; end
c = C.new
class <<c; def bar; puts "bar"; end; end
c.bar ==> "bar"

Even though the class of c was C, the singleton of c held a method called bar, which we could invoke. As Why the Lucky Stiff says, "the hidden singleton lurks behind everything."

Now the singleton is an object in its own right, and can even have its own singleton. Most people don't find this useful. One thing that people do find useful is pulling out the singleton from an object with a construct like
def get_singleton; class <<self; self; end; end

Of course, the real fun comes when you start playing with singletons of Classes. Since Classes are Objects in Ruby, they also have singletons. I can't say that I understand all the implications yet. But you sure can do some cool things.

Note: some people call singletons "metaclasses," but the language designer views that as a misnomer.