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!
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
Gary Wright pointed out that you can only have one instance for a given Fixnum. For example, if you write :
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.