So far I’ve talked about how everything was an object in ruby, even classes. I also wrote an article explaining what were the most important steps to follow when trying to understand ruby classes and objects. This wasn’t a bad idea, but it was a rather simplistic view. I think we’re ready to dive into the heart of the object model. Now my objective is not to give you a vague idea about how the ruby object model might work, I want to show you clearly what’s going on behind the scenes. Since I am not a fan of long posts, I have decided to split it in two parts. Here is part 1 :
It’s not that the ruby object model is hard to understand, in fact it is quite simple and coherent, but in order to understand it you’ll need to be concentrated, open minded as well as having a decent understanding of dynamic languages.
A simple case
class MyClass
def my_instance_method
"I'm an instance method"
end
def MyClass.my_class_method
"I'm a class method"
end
end
obj = MyClass.new
Let’s try to understand where does the various elements are located :
What is contained inside the object “obj” ?
- some flags (we won’t bother about that in this post)
- instance variables (describe the state of “obj”)
- a reference to the class, that is : MyClass
Ok fine, but where are the methods? We have to follow the reference to MyClass to find them.
What is contained inside the object “MyClass” ?
- some flags
- Instance variables (describe the state of “MyClass”. From “obj” point of view, it’s the class variables, those you reference with @@)
- a reference to the super class (if any. In this case, it is “Object”)
- a reference to the class (what? I’m confused now!)
- Methods (Ahh! Here they are! From “obj” point of view, these are INSTANCE methods)
You said a “reference to the class” ? I beg your pardon?
First of all, let’s not confuse the super class with the reference to the class. The super class is a reference to the ancestor of the current object (in this case, the ancestor is Object), while the reference to the class contains additional information about the current object.
That’s fine, but it doesn’t explain the purpose of that “reference to the class” thing. Aren’t we already inside the class “MyClass” ? Yes, we are. The reason why we need a reference to something else is because we need a place to store the class methods! We have to put them somewhere right? The methods described at point #5 are instance methods. These methods will only exist in the instances you created for class MyClass. They won’t exist in the object MyClass.
That “reference to the class” is in fact a reference to a special class (the pickaxe book call it a meta class) that will hold the methods for the object “MyClass”. Those are what we call class methods (from “obj” point of view at least). It makes a lot of sense when you think about it. Remember, classes are objects… so there’s no reason they cannot have their own methods. if “obj” is able to store it’s methods inside “MyClass”, “MyClass” has to be able to store it’s methods in some other place too : This place is the meta class. You can’t have access to these classes directly, they are completely hidden.
I’ll stop right there for now. In the next (and last) part of this serie, I will talk about the “chain” that ruby follows to find and invokes instance and class methods.
Instead of:
def MyClass.my_class_method
I think you can also use:
def self.my_class_method
Yes he could, but it’s just a taste 🙂
Agreed. Actually there is another article on this site saying the exact same thing – I didn’t see it prior to posting! I personally prefer self because I think it is more explanatory of what it is plus if you ever change the class name then you don’t need to do a find/replace.
yes.very good!
Nice article, thanks. One important thing: instance-variables on class levels and class-variables are NOT the same. For example the class-variables are visible in all subclasses and can be altered. See http://gist.github.com/398291 and the excellent http://railstips.org/blog/archives/2006/11/18/class-and-instance-variables-in-ruby/