I made a simple list describing the 3 main things to consider when trying to understand how objects work in ruby. Feel free to add to this list as much as you want. Your comments are welcome and very appreciated.
1) The starting point is the object, not the class
To understand how objects and classes behave in ruby, we have to stop thinking in terms of classes and start thinking in terms of objects. Why? Because in ruby, a class is also an object. Every classes you are defining are instances of a class named Class. Each of these instances contains everything related to the structure of the object. Only one instance for each class definition is needed in a typical ruby / rails application. I mean, there would be no need to have both String.new() and String2.new(). Just one factory to create String instances is enough. However, if for some strange reason you would like to clone the definition of a class in another instance, you could still do it.
String2 = Class.new(String)
my_string = String2.new("How useful!")
my_string.reverse
2) An object structure is not frozen and can be altered at any time
When you’re done defining your class and you put the end keyword, don’t think that this object (remember, a class is an object) is “safe” from future modifications, it isn’t. Everyone can modify your class structure. I know that dynamic languages are not for everyone (I imagine Java and C++ programmers shaking their heads in desperation right now…), but I personally find the freedom that they offer to be truly amazing.
class NoOneIsSafe
def my_method
"I'm in my_method"
end
end
#Now, let's create a mess
def im_hacking_this_object!
"Muhahahahaha!"
end
#I just realized that the following code does not what
#I really thought it would. Read the update below
NoOneIsSafe.send(:public, :im_hacking_this_object!)
obj = NoOneIsSafe.new
obj.im_hacking_this_object! #output : Muhahahahaha!
#UPDATE 03/30/2007
Even if the above code really changed NoOneIsSafe structure, I realized that it also changed the structure of every single instances! Whatever you write some_obj.methods, String.methods, MyCustomClass.methods, you will see the im_hacking_this_object! method everytime. It’s definitely NOT something a sane person would want to do.
You could also add a method to a single instance of an object, like this :
class NoOneIsSafe
def my_method
"I'm in my_method"
end
end
obj=NoOneIsSafe.new
obj2=NoOneIsSafe.new
def obj.my_other_method
"I exist in this instance only"
end
obj.my_other_method #it works
obj2.my_other_method #won't work
3) Things that don’t look like objects often are
When trying to understand how objects work in ruby, you have to put the following sentence in the back of your head at all time : “Objects are everywhere… even if I can’t always see them“. A trivial statement like result = 5 + 3 must be understood the following way :
- The “+” method of the Fixnum instance named “5” is called
- The Fixnum instance named “3” is passed as a parameter to the “+” method.
- The result of the call is a FixNum instance and is assigned to an object called “result”, which in turn becomes a FixNum instance
I talk about those hidden OO mechanisms in the following articles :
– Oh Ruby, who are you trying to fool?
– A trap to avoid with Ruby assignments
#UPDATE 03/31/2007
Gary Wright pointed out that you can only have one instance for a given Fixnum. For example, if you write :
a=1
b=1
c=1
1, a, b and c will all point to the same space in memory (Actually, these are not 4 different references to the same object. they are the same object). When you write 5 + 3, 5 already is a FixNum instance. The name of this instance is 5. Thanks to Gary for clearing this out.
> An anonymous Fixnum instance is created and initialized with the decimal value 5
This is inaccurate. A Fixnum instance doesn’t contain a value, it *is* a value.
5 is simply the name of the particular fixnum that behaves like the number 5. There is only one such fixnum in the same way that there is only one number 5.
Gary,
I realize you are right. I’m going to update my post about that.
I made a visualization of the ruby object model and inheritance hierarchy in case anyone is interested: https://mitya777.github.io/dev/2015/06/08/ruby-object-model/