9.4 Singleton methods and metaclasses

Who holds the behaviour?

An important characteristic of an object is that you can send messages to it and the object can respond to them. The usual way of sending messages in Ruby is by invoking methods. The methods are defined in a class definition - all instances of this class will respond to those methods.

So, who holds these methods? Is it stored only in the class definition, or does each instance carry a copy of its entire behaviour, like the DNA does? Let us find out for ourselves.

Example Code:

Output Window

Singleton methods

Since all methods are implemented and stored by the class definition, it should be impossible for an object to define its own methods. However, Ruby provides a way around this - you can define methods that are available only for a specific object. Such methods are called Singleton Methods. Let us look at an example of a singleton method:

Example Code:

Output Window

The respond_to? method tells us whether the object can respond to the given message. Apparently, no new instances of Foo can respond to shout - only the object to which this method was added to can. Thus it appears that the object foo holds the method shout all by itself.

Here the object foo has the singleton method shout. This is a singleton method because it belongs to just one instance of a class and will not be shared with others.

However, singleton methods contradict what we found early: instance objects cannot hold methods, only class definitions (objects of class Class) can. It happens that the truth is somewhere in-between.

When you declare a singleton method on an object, Ruby automatically creates a class to hold just that method. This class is called the 'metaclass' of the object. All subsequent singleton methods of this object goes to its metaclass. Whenever you send a message to the object, it first looks to see whether the method exists in its metaclass. If it is not there, it gets propagated to the actual class of the object and if it is not found there, the message traverses the inheritance hierarchy.

In summary:

  • Objects in Ruby only store the state. Its behaviour comes from its class definition.
  • Objects can also have methods that are independent of the parent class definition. They are called singleton methods and are stored on the metaclass of the object. The metaclass is typically invisible to the programmer.

It is possible to access the metaclass of an object through a neat trick:

Example Code:

Output Window

Lets first focus on the a object. As you can see, we've added a singleton method shout to it. This method is verified to exist as an instance method in a's metaclass.

Now let look at how the metaclass method is implemented. The class << self syntax changes the current self to point to the metaclass of the current object. Since we are already inside an instance method, this would be the instance's metaclass. The method simply returns self which at this point is the metaclass of the instance.

A metaclass is almost a class in many respects. It however can't be instantiated:

Example Code:

Output Window

The metaclass method approach to inspect metaclasses in Ruby was popularized by _why through his metaid.rb.

Ruby 1.9 introduced the singleton_class as a shorthand for the class << self syntax we saw earlier. From now on, you can just call the singleton_class instead of our custom metaclass method.

Hint

A singleton method exists as an instance method in its singleton_class, but not in the actual class of the object.

Output Window

In Ruby, both 'metaclass' and 'singleton class' means the same. You'll find them being used interchangeably in Ruby literature.

Metaclasses are the underlying mechanism using which Ruby provides us an object model with inheritance and mixins. However, you would rarely find this concept being used while writing Ruby code. . This is because Ruby ensures that the abstraction doesn't leak and effectively hides the semantics of metaclasses from the programmer. Even though this is the case, understanding metaclasses well helps in understanding Ruby's object model better.

Congratulations, guest!


% of the book completed

or

This lesson is Copyright © 2011-2024 by Jasim A Basheer