Monday, June 08, 2009

Ruby Method Lookup

There are three different kinds of methods containers in Ruby, Classes, Modules and Singleton Classes. When a method is invoked all of them are searched for the first matching method to execute.

A class may contain methods

class Mammal 
  def breathe
  end
end

A class may inherit its methods from one other class.

class Tapir < Mammal
end

A class may also mix in methods from several modules.

class Tapir 
  include Swimmable, Runnable
end

Methods may also be defined on the object itself, this is actually the anonymous Singleton Class that is available to every object.

kjell = Tapir.new
# kjell can not only swim, he can crawl
def kjell.crawl 
end

So what happens if all these different method containers define the same method? How will the interpreter know what to execute?

When a method is called:
  • The Singleton Class is searched. —the anonymous class of kjell
  • The modules included in the Singleton Class is searched. —in this case none.
  • The class is searched. —this is the Tapir class
  • The modules included in the class is searched in reverse order of inclusion, the modules override each other as they are included. —Runnable, then Searchable
  • Then the search continuous in the superclass of the class and the modules included in it.
  • If the search reaches the top of the hierarchy and no method is found, method_missing is invoked on the initial object and the search for method_missing follows the same path.

That’s almost it. There is one caveat. If the Singleton Class is a meta-class, that is the singleton class of a class, then the class belongs to a meta-class hierarchy that parallels the hierarchy of the normal classes. This allows for inheritance of class methods and gives us the ability to override class methods such as new. The lookup path is changed to search the meta-class’ superclass after step two, before the class of the class (i.e. instance methods of class Class).

No comments: