Classes and Objects
Classes and objects are obviously central to Ruby, but at first sight they can seem a little confusing. There seem to be a lot of concepts: classes, objects, class objects, instance methods, class methods, and singleton classes. In reality, however, Ruby has just a single underlying class and object structure, which we'll discuss in this chapter. In fact, the basic model is so simple, we can describe it in a single paragraph.
A Ruby object has three components: a set of flags, some instance variables, and an associated class. A Ruby class is an object of class
Class
, which contains all the object things plus a list of methods and a reference to a superclass (which is itself another class). All method calls in Ruby nominate a receiver (which is by default
self
, the current object). Ruby finds the method to invoke by looking at the list of methods in the receiver's class. If it doesn't find the method there, it looks in the superclass, and then in the superclass's superclass, and so on. If the method cannot be found in the receiver's class or any of its ancestors, Ruby invokes the method
method_missing
on the original receiver.
And that's it---the entire explanation. On to the next chapter.
``But wait,'' you cry, ``I spent good money on this chapter. What about all this other stuff---singleton classes, class methods, and so on. How do they work?''
Good question.
How Classes and Objects Interact
All class/object interactions are explained using the simple model given above: objects reference classes, and classes reference zero or more superclasses. However, the implementation details can get a tad tricky.
We've found that the simplest way of visualizing all this is to draw the actual objects that Ruby implements. So, in the following pages we'll look at all the possible combinations of classes and objects. Note that these are not class diagrams in the UML sense; we're showing structures in memory and pointers between them.
Your Basic, Everyday Object
Let's start by looking at an object created from a simple class. Figure 19.1 on page 239 shows an object referenced by a variable,
lucille
, the object's class,
Guitar
, and that class's superclass,
Object
. Notice how the object's class reference (called
klass
for historical reasons that really bug Andy) points to the class object, and how the
super
pointer from that class references the parent class.
When Ruby executes
Guitar.strings()
, it follows the same process as before: it goes to the receiver, class
Guitar
, follows the
klass
reference to class
Guitar$'$
, and finds the method.
Finally, note that an ``S'' has crept into the flags in class
Guitar$'$
. The classes that Ruby creates automatically are marked internally as
singleton classes. Singleton classes are treated slightly differently within Ruby. The most obvious difference from the outside is that they are effectively invisible: they will never appear in a list of objects returned from methods such as
Module#ancestors
or
ObjectSpace::each_object
.
Object-Specific Classes
Ruby allows you to create a class tied to a particular object. In the following example, we create two
String
objects. We then associate an anonymous class with one of them, overriding one of the methods in the object's base class and adding a new method.
a = "hello" |
b = a.dup |
|
class < |
def to_s |
"The value is '#{self}'" |
end |
def twoTimes |
self + self |
end |
end |
|
a.to_s |
|