Home > Programming > Understanding the Ruby object model

Understanding the Ruby object model

Not a very long time ago, I found the Ruby object model very confusing. Part of my problem was that I was trying to model the relationships as a directed acyclic graph, whereas in reality, the model contains cycles. I’m guessing that others have found this confusing, so I’m going attempt to explain how it works in a way that my past self would have understood! Note that this is a basic explanation, and glosses over higher-level concepts like the eigenclass/metaclass (I’ll leave that for a later post).

Different things in Ruby

There are just a few things that exist in Ruby that you need to understand to really grok its object model.

Objects

Everything is an object. You can’t get very far into Ruby-land without hearing that phrase. It’s true though, everything in Ruby is an object. The interesting thing is how those objects are linked together and classified.

Classes

All objects are instances of a class. There are three special classes that are the key to understanding the Ruby object model: Object, Module and Class. More on them later.

Relations

Like I said before, it’s the links between the different objects that explain how the Ruby object model works.

Instance of/class

All objects have a class – they are instances of that class. That means that whenever you have a class, you can call .new on it to get an instance. And whenever you have an instance, you can call .class to get its class. This seems obvious, but it can get confusing when you remember that everything is an object, and so everything is an instance of a class.

Superclass/subclass

All classes have a link to a superclass. If you don’t explicitly inherit from another class in a class definition, that class will inherit directly from the Object class.

How they fit together

Here’s some code to play with:

class Animal
end

class Dog < Animal
end

fido = Dog.new

Once you know what the pieces and the relations are, it’s fairly straightforward to piece them together. All classes are an instance of Class. That includes the class Class, so there’s a circular relation there (which isn’t a problem).

Dog will basically have the following inheritance hierarchy (the superclass links):

Dog < Animal < Object < BasicObject

(Ruby 1.9 introduced BasicObject as Object‘s superclass.)

The Class class has the following inheritance hierarchy:

Class < Module < Object < BasicObject

Anything that’s a class (so BasicObject, Object, Module, Class, Animal and Dog here) has Class as its class – they’re all instances of Class. Any other objects have their own classes. So fido above will have a class of Dog, 3 has a class of Fixnum, “an awesome string” has a class of String, etc. All those classes inherit from Object ultimately (although classes like Fixnum have their own complex inheritance hierarchies).

To finish things off, here’s a little diagram of what I’ve just described, showing all the class and superclass links.

The Ruby object model

Categories: Programming Tags: ,
  1. Marco
    August 9th, 2011 at 10:43 | #1

    What´s the point of calling a class of class? Like this circular thing, where class is a instance of class, why such thing should be important?

  2. August 9th, 2011 at 10:49 | #2

    @Marco A class is an object, so just like any other object it needs to have a class. If you have an object and you don’t know if it’s a class or not, you can ask it what its class is. The fact that Class is an instance of Class is just an interesting fact that arises from the model. It’s not necessarily going to be something you use every day.

  3. STEVEN SEAGAL
    August 9th, 2011 at 13:49 | #3

    Class.class.class.class.class.class.class.class

  4. Name
    August 9th, 2011 at 13:53 | #4

    Looks like all classes originate in an intersection of blue lines.

  5. August 9th, 2011 at 13:54 | #5

    @STEVEN SEAGAL How about this:

    #is this object the Class class?
    def is_Class? obj
      obj.class == obj
    end
    

    :)

  6. Name
    August 9th, 2011 at 13:55 | #6

    Oh wait. Sorry. Didn’t spot that small blue arrow pointing into Class. All classes originate in class, then. Classy.

  7. August 9th, 2011 at 13:58 | #7

    @Name Yeah, without drawing curvy arrows is was a bit tricky to make it obvious where all the lines went, but I feel like the text + the diagram conveys it.

    Also, classes are all instances of Class which makes sense if you think about it. They all inherit from Object though – the point of this article was to highlight the difference between the class and superclass associations.

  8. August 9th, 2011 at 13:59 | #8

    Much like turtles, it’s classes all the way down.

    http://en.wikipedia.org/wiki/Turtles_all_the_way_down

  9. August 10th, 2011 at 04:49 | #9

    @Skilldrick

    So you’ve basically just re-implemented #instance_of? there, yeah? http://ruby-doc.org/core/classes/Object.html#M001032

    One is ordinarily more interested in `#kind_of?` instead (if one can’t just pure ‘duck type’), which will return true if the object is an instance of the argument OR is an instance of a class which has the argument as one of it’s superclasses. `#kind_of?` will work on Modules too.

    You could also re-implement `#kind_of?` yourself, using the `#class` and `#ancestors` (http://www.ruby-doc.org/core/classes/Module.html#M000475) methods, which would be an interesting exersize to make sure you understand what’s going on.

  10. Devyn
    August 10th, 2011 at 05:00 | #10

    @Skilldrick You can use .instance_of? instead. For example, 2.instance_of?(Fixnum) returns true.

    If you want to know if an object could be treated as, say, a Numeric, you can use .is_a? / .kind_of?. They’re synonyms.

    2.is_a?(Numeric) #=> true, because 2's class inherits from Numeric.
    2.kind_of?(Numeric) #=> true
    2.instance_of?(Numeric) # => false, because 2 is not a direct instance of Numeric
    
  11. August 10th, 2011 at 09:11 | #11

    @Jonathan Rochkind No, that code snippet was a joke really. Look at the capitalisation in the method name: is_Class?. The method checks to see if its argument is the Class class, as that is the only object in Ruby whose class is the same as itself (obj.class == obj). It’s not at all useful, just thought it was amusing :)

  12. August 10th, 2011 at 09:15 | #12

    @Devyn Absolutely – it’s much better to rely on instance_of? or duck typing than explicitly checking the class. I was just showing how you’d use the .class relationship if you wanted to.

  13. August 11th, 2011 at 17:54 | #13

    I think it would help the diagram a to see the arrow coming out of the blue line on Fixnum. As is, it looks like you’re saying Numeric, Object, and BasicObject are instances of Fixnum. In reality, the line doesn’t go straight past the line to Class, but instead joins it, but since there is no arrow on the other side, this must be determined by realizing the graph doesn’t make sense and thinking about it a bit.

  14. alexey
    August 13th, 2011 at 10:16 | #14

    @STEVEN SEAGAL that’s very classy :)

  1. August 9th, 2011 at 17:08 | #1

Comments parsed as Markdown.