Why classes are confusing in Ruby
I wrote before about how Object
and Class
are confusing in Ruby. I think I know what’s so confusing about it now.
In most other OO languages there are two concepts, objects and classes. Objects are instances of classes, and classes can be subclasses of other classes. Basically, each object or class has what could be described as a pointer. An object has a pointer to its class, and a class has a pointer to it’s superclass. In Java, where every class inherits directly or indirectly from Object
, there is a clear line from each individual object to the Object
class, via the object’s class and its class’s superclasses. Let’s take Bob, an employee:
class superclass superclass
bob -> Employee -> Person -> Object
There’s a clear line from bob
to Object
, via bob’s class, and his class’s superclasses.
In Ruby, there’s still this line, but because classes are objects as well, there’s an extra line. There isn’t one pointer - there are two. Each class has a class and it has a superclass. That’s how you get to the point where Class
is_a
Object
, and Object
is an instance_of
Class
. Here’s some beautiful ascii art to illustrate:
Class -------> Module -------> Object
^
| Class --------> Module -------> Object
| ^
| |
Class -------> Module -------> Object
^
| Class --------> Module -------> Object
| ^
| |
Employee ------> Person -------> Object
^
|
bob
Every vertical pointer describes an instance_of
relationship. Every horizontal pointer describes an is_a
relationship. I haven’t drawn all the instance_of
relationships of the classes, because if I did I’d be drawing an infinite tree of Class
, Module
and Object
nodes, and I don’t have time tonight to do that.
That’s what makes Object
and Class
so confusing in Ruby. In most other OO languages that use Object
as the overall base class, there is a straight line between an object and Object
(with multiple inheritance you can get diamonds, but it all gets back to the one Object
eventually). With Ruby, if you follow all the relationships you end up with an infinite tree.
Of course, this is only because I’m insisting on following all the instance_of
relationships. In most circumstances you can just forget that classes are objects, and only follow the is_a
relationships. The only instance_of
relationships that usually matter are between non-class objects and their classes. But if you follow the rabbit hole, you’ll find just how deep it goes …