The Metaclass
If you search around the web a bit, you are sure to find the Ruby Metaclass defined as “The singleton class of a class.” While this definition is accurate, it doesn’t contribute to an understanding of why Metaclasses exist. It is also guilty of underplaying some notable difference between Metaclasses and “normal” Singleton class.
Before getting into Metaclass details it might be useful to clear up a bit of terminology. Unfortunately, terminology around Ruby’s object model is not used consistently in existing literature, MRI source, JRuby source, or throughout the community. A prime example of this is the rb_make_metaclass function in MRI, which is used to make both Metaclasses and Singleton classes. That said, the following glossary is the one I stick with, and recommend to others.
- Singleton Class: Hidden Ruby class for storing instance specific behavior
- Metaclass: The Singleton class of a Class object. Differs in some ways from a “normal” Singleton class. Occasionally inappropriately used as a synonym for Singleton class.
- Eigenclass: Alternative name for a Singleton Class. Eigenclass (roughly “own class” in German) has the advantage of not having a well known OO design pattern named after it. It’s preferred by some of the Ruby elite, but has never really caught on with the community at large.
- Virtual Class: Alternative name for a Singleton Class. Best avoided. In the current MRI implementation, there is nothing particularly virtual about these classes and virtual is already a very loaded term in the OO community.
Take a look a page 382 of PickAxe, Second edition for some additional background on Metaclass terminology.
With diction out of the way, focus can return to the question, “What is it that Ruby wants that forces Metaclasses to exist?” This can be answered in a number of ways, but one simple answer is “Ruby wants class methods.”
Take this simple factory method…
Understanding what happens when the create_by_country message is sent to Pirate is not difficult if one bares in mind Ruby’s “everything is an object” ethos. If Ruby is going to treat the Pirate class as an object, then the class should have a klass pointer and flags collection.
Looking at the definition of the RClass struct confirms that the Pirate class is doing it’s part…
RClass references an RBasic struct which includes a klass pointer and flags collection. Note that with the inclusion of an iv_tbl, the data members of RClass are a superset of RObject’s members. Put another way, anything represented by a RClass struct fulfills Ruby requirements for “objectness”. Once it is understood that the Pirate class is itself an object, understanding how the create_by_country message is handled becomes a matter of understanding method dispatch. When the Pirate class receives the create_by_country message, the interpreter follows Pirate’s klass pointer and inspects the m_tbl it finds there for a method named create_by_country.
Pirate is an instance of Class, and so at first glance one would think that the class returned by Pirate’s klass pointer should be the Class class. The problem is Ruby can’t store create_by_country in Class’ m_tbl, or all instance of Class, that is to say every class in the Ruby process, would have access to the method. This problem should sound familiar. create_by_country is actually instance specific behavior for the Pirate instance of Class. Since instance specific behavior is stored in Singleton classes, Ruby does what it knows, and creates a Singleton class for Pirate to store the create_by_country method body. This special Singleton class, found by following the klass pointer of a class instance is called a Metaclass.
If that were all there is to Metaclasses, The Pirate class object model would look something like this…

It turns out that Ruby needs a bit more from classes. Since classes are objects, Ruby wants them to play nicely in an Object Oriented playground. All the other children in that playground know a game called polymorphism, and so classes must too. Assume that the Pirate class inherits from the Human class. Polymorphism (and Liskov’s Substitution Principle) say that any instance of Human can be replaced with an instance of Pirate. That is to say a Pirate is a Human, and so we can expect it to do all the things a human does; eat, sleep, etc…
Ruby wants this principle to be extended to classes. So if Pirate extends Human, then the Pirate class is a Human class, and any class methods exposed by Human should be available as class methods on Pirate. “Normal” Singleton class creation doesn’t support Ruby’s desire on this. Remember that for a non-class Ruby object, the Singleton class replaces the “real” class, which stays in the dispatch loop via the super pointer on the Singleton class. If Metaclasses worked the same way, then the Human/Pirate object model would look something like this…

A message sent to Pirate would never be dispatched to ‘Human’s m_tbl. If Ruby wants classes to be polymorphic, the interpreter needs a way to move from the Metaclass of Pirate to the Metaclass of Human when dispatching class methods. The sanest way the interpreter can do this, is to use ‘Pirate’s super pointer, and so that is what it does.
The creation of “normal” Singleton classes and the creation of Metaclasses is handled by two different lines of code. A quick look at this code makes this all a bit more concrete…
The second parameter to rb_make_metaclass will be used as the super pointer for the Singleton class that will be created. Note that when making a “normal” Singleton class, this parameter is the current class of the object under manipulation. When the object is itself a class however, as in rb_class_initialize, the second parameter is the class found by following the klass pointer of the object’s super pointer. This is a bit convoluted, in fact it leads to one of the most confusing sentences in Ruby, “The superclass of the Metaclass is the Metaclass of the superclass”. A corrected diagram clears this up…

With the object model arranged this way, the interpreter is free to use standard method dispatch to resolve messages sent to a class object. Note an additional bit of weirdness in this diagram. An instances of Human is an instance of Object. This means that the Human class has an is a relationship with the Object class and should have access to any class methods that might be stored on Object. Standard Metaclass rules apply, the super pointer of the Metaclass of Human must point to the Metaclass of Human’s superclass, Object.
Creating this parallel inheritance hierarchy as new classes are defined is one thing, but it would be painful in the extreme to have to re-situate the super pointers of all subclasses the first time a class defined a class method. Ruby avoids this pain in an interesting way. Notice that the code example above, to create the Metaclass, was extracted from a function named rb_class_initialize. As this implies, Metaclasses are created at the time of a classes initialization. This is markedly different form “normal” Singleton classes which are instantiated “on demand” at the time of first access.
As always, I hope you find this useful. If you are looking for more in depth coverage of the Metaclass be sure to check out the translated fourth chapter of The Ruby Hackers Guide. Comments, questions, and corrections are always appreciated.
October 6th, 2007 at 7:27 am
It’s a nice article, shame the image links are broken! You need to replace src=”images/…” by src=”/images/…” to fix them.
October 6th, 2007 at 7:43 am
Strange. It was fine all day yesterday and even first thing this morning (that eye means I’m watching). I wonder if dreamhost just did something odd with the virtual host or patched WordPress on the sly. Can’t imagine how my paths would have worked to begin with. Either way, thanks very much for the heads up. Changed the image paths to absolute and all is well again.
October 7th, 2007 at 6:51 am
Excellent article. BTW, how did you generate the images? Dia?
October 7th, 2007 at 1:46 pm
Hi Daniel, Thanks for the comments and for reading the posts. I’m using OmniGraffle. I’m awful with it so each diagram takes me somewhere between 30 minutes and 212 hours.
December 9th, 2007 at 5:52 pm
Awesome article. It’s helped cement my understanding of the 4th chapter of the Ruby Hacking Guide (which is pretty heavy stuff, at least for me).