I’ve noticed some confusion lately on the part of some newcomers to Ruby about how methods are found at runtime, and in particular, the relationship between instance and class methods.
A week or so ago, someone posted some questions on ruby-talk about this issue, and then today I ran across this blog review of David Black’s “Ruby for Rails” which contained this:
On every method call, Ruby will search its object space in the following order:
- Current instance, followed by class methods
- Mixed in methods
- Superclass instance (repeat 1)
- Object methods, followed by Kernel mixin
I often get confused with mixin, class, and instance method precedence, so this is a useful model to revisit and keep in mind.
I don’t know where that reference to class methods in item 1 came from. I don’t think David said that in his book.
Here’s how it really works
Here in the form of answers to the questions posed on ruby-talk last week is my explanation of how Ruby finds methods when a message is sent to an object
Q: Do all inheritance chains and all objects have a homologue
> metaclass at all times, which are behind the scenes?
In ruby metaclasses are singleton classes of classes. Just as a class
holds the table used to find the methods of its instances, the
metaclass holds the table used to find methods for its sole instance
i.e. the class.
The singleton class which serves as the metaclass of a class is
created when the class is created. This is done internally by the
Ruby interpreter.
While object’s don’t have metaclasses they can have singleton classes,
which are created when needed, e.g. when you do something like:
a = "abc" b = "def" def a.method end # singleton class for the object referenced by a is created now class <<b #singleton class for the object referenced by b is created now end
Q: Do a chain of metaclasses spontaneously appear at the moment when a class is used as a receiver : so to be used to call a method inside of a parentclass?
No, as I just said, metaclasses are created along with their
corresponding class. The metaclass’ superclass is set to the
metaclass of the classes superclass.
Since I first wrote this I’ve gotten some feedback that the last sentence is a little hard to digest, so here’s an example. Let’s say we create a class MyNiftyClass as a subclass of Object. The singleton class of the class object referenced by the MyNiftyClass global gets created at the same time as class object, no waiting for one of the things which trigger the creation of a singleton class for a non-class object. Thesuperclass of the MyNiftyClass is set to object, and the superclass of MyNiftyClass’ metaclass is set to Object’s metaclass.
Besides the fact that their creation occurs immediately, there is one other difference between
singleton classes of objects and singleton classes used as
metaclasses. The later can have subclasses, while the former cannot.
Normal object singleton classes have their internal superclass set to
the original class of the object.
Note that I’m using superclass and class here to describe the internal
relationship. Ruby’s class and superclass methods don’t always give a
true picture when singleton/metaclasses are involved. I personally
think of the class-like objects linked together with the superclass
field as a behavior chain since it’s used to implement the behaviour
of one or more objects.
Q: How can a metaclass contain more methods than its corresponding class has. Can you give an example of the code in the next addition(sic)?
The number of methods in the class and the number of methods in the
metaclass is completely independent, for example, look at the
following and compare it to what I said in reponse to question #1
class MyClass
def initialize # This defines the initialize method in MyClass which
# Like all such methods are available to INSTANCEs
# of the class, and its subclasses
end
def method1 # another instance method
end
def MyClass.class_method # This defines a class method in the
# singleton class of MyClass (i.e. the metaclass)
# which is available to instances of the
# metaclass and its subclasses
end
def self.class_method_2 # This adds another class method, it's
# Just a different syntax for the last form of
# definition since within the scpe of a class
# definition, self is bound to that class
end
class << self # or equivalently class << MyClass
# Now we are in an inner scope, that of MyClass' metaclass
def class_method_3 # So this also becomes a class method
# of MyClass
end
endSo MyClass has two instance methods (plus those it inherits from
Object) and three class methods (plus those the metaclass inherits from
Object’s metaclass.
As a related note, when a class includes a Module, another kind of
virtual class is inserted between the class and it’s superclass. This
virtual class (or I_Class) looks like a class but has a pointer to the
method table of the module instead of having its own table. This
lets modules appear in different behavior chains and lets those
including them see updates to the module when they are made. There
are some other fields of the module which are also copied, but I’m not
going to mention them here since they aren’t relevant and might
confuse.
Q: Which is searched first in the inheritance chain. methods in
the proper parents, or methods in the meta parents?
There’s no cross over at all. When finding a method for an object,
Ruby gets the head of what I called the behavior chain. For a normal
object with no singleton class, this will be the class, For an object
with a singleton class this will be the singleton class. If the
method is found, then it’s used, if not the next class-like thing in
the behavior chain is examined and so forth. The keyword super makes
the search start in the next link in the behavior chain after the one
in which the current method was found.
So if you’re invoking a method on a normal object, no metaclasses will
be on the chain. If you are invoking a method on a class, then the
behavior chain will consist of metaclasses, except that the superclass
of Object’s metaclass is Class. If you think about this hard enough it
makes sense, since the instance methods of Class are for use by
classes.
So if we have:
class B
...
end
b = B.new
b.to_sThe search goes:
B → Object → (I_Class wrapper for Kernel)
the last is because Object includes Kernel
and
B.newthe search goes
(singleton of B) → (singleton of Object) → Class → Module →Object → (I_Class wrapper for Kernel)
Q: If a method is found is the search stopped even though another method with the same name might exist in a parallel chain?
As I just described, the parallel chain is irrelevant, it isn’t
considered at all.





Well, that was a remarkably clear explanation of everything :-) I wasn’t too confused as to what was going on, but well done regardless.