[fundamental] Inside Ruby Objects and Classes
As we've already known, Ruby's an OOP language so understanding about Class and Object plays a crucial role when becoming a professional Ruby programmer. In this post, I want to dig into structure and organization of fundamental elements, Object and Class which all of Ruby dev familiar with. 1. ...
As we've already known, Ruby's an OOP language so understanding about Class and Object plays a crucial role when becoming a professional Ruby programmer. In this post, I want to dig into structure and organization of fundamental elements, Object and Class which all of Ruby dev familiar with.
1. Ruby Object
Basically, Ruby doesn't compile and run the application by itself so they need the help from C language. All the Ruby objects are kept in C structure named RObject which's organized like bellow For easily explaining, I'll take a simple class as an example
class Car attr_accessor :type #Sport, Sedan,.. attr_accessor :cylinder_capacity end
Each Ruby object's assigned with specific VALUE which's implicit its pointer
RObject contains RBasic inwhich:
- flags: a set of Boolean values store internal technical values
- klass: refer to Class created current object
2.1.5 :001 > jimmy_car = Car.new => #<Car:0x007f9751a0c6a8> 2.1.5 :002 > jimmy_car.type= "Sports" => "Sports" 2.1.5 :003 > jimmy_car.cylinder_capacity= "2.0" => "2.0" 2.1.5 :004 > jimmy_car => #<Car:0x007f9751a0c6a8 @type="Sports", @cylinder_capacity="2.0">
We can easily detect the Class name is Car while the hexa value 0x007f9751a0c6a8 is implicit VALUE
Besides, RObject also provide two other fields to store instance variable:
- numiv: the number of instance varibale
- ivptr: a pointer to an array of values of instance varibales
With above example, numiv, ivptr receive value 2 and point to array ["Sports", "2.0"]
To sum up, we can simplify
Every Ruby object is the combination of a class pointer and an arrays of instance varibales
2. Ruby Class
If we consider each Ruby object as an item in supermarket, the Ruby Class,which created the objects, must be a factory carrying complicated functions and organization. Therefore, I'll go step-by-step to through each part with different features of a Ruby Class. So, Let start with opened summary then it'll be completed when we know everything about Ruby Class
"A Ruby class is"
Methods and attributes
Comming back to first part example with Car class
class Car attr_accessor :type #Sport, Family... attr_accessor :cylinder_capacity end
In here, attr_accessor's just a shortcut of group methods aim to defining, getting, setting for attribute. The full version of Car class should be
class Car def type @type end def type=(value) @type = value end def cylinder_capacity @cylinder_capacity end def cylinder_capacity=(value) @cylinder_capacity = value end end
All these methods appear in every Ruby class which's a group of methods definations. All objects're born by class owning above methods that calling object methods. Then we have first feature of Ruby class
"A Ruby class is a group of methods definations"
In fact, the functions above also used two varibales: @type and @cylinder_capacity and RObject stores just instance varibale values, not their names. So RClass definitely comprises attribute name.
Interestingly, Ruby classes are based on Class class, as a consequence, class is an object. As we conducted above, "Every Ruby object is the combination of a class pointer and an arrays of instance varibales". Now we can visualize some components inside RClass
A Ruby class is a group of method definitions and a table of attribute names.
Inheritance
All of us know about inheritance, a siginificant feature of Object-oriented programming and Ruby Classes definitely have this precious gift. To do this, in each Ruby Class, there's a space to specify superclass and in the case we don't have superclass, Ruby will use Object class as the superclass. For example, class Car can be inherited from Vehicle
class Car < Vehicle ...
Then now, class Car can use some variables and function which've already defined in Vehicle class. And now, we have a newer version of Ruby Class
A Ruby class is a Ruby object that also contains method definitions, attribute names, and a superclass pointer.
Constants
class Car < Vehicle EMISSION_STD = "EURO 2" ...![RClass_last_step.jpg](/uploads/1a523a5c-d339-4368-9cfe-8b428bd859d1.jpg)
Sometimes, in Class, we need to declare constanst which always start with capital letter. Many people refer constants as global varibale of Ruby Class, actually its properties have some differences with variable such as warning when changing constant value. Therefore, our RClass cannot skip this part
A Ruby class is a Ruby object that also contains method definitions, attribute names, a superclass pointer, and a constants table.
Then now we own a completed view about Ruby Class
3. Specialities of Ruby class
We've already known how Ruby Object and Class are constructed but I think there're some vague points for us when using RClass. This part'll point out two most confusing features of Ruby Class
Class Instance Variable vs Class Variables
Let add some variables to our Car classs
class Car < Vehicle ... @engine = "Diesel" @@automative_electronics = true class << self def engine_name @engine end def electronics_controlling? @@automative_electronics end end end
Now our Car class has two new variables:
- @engine: class instance variable
2.1.5 :001 > Car.engine_name => "Diesel"
- @automative_electronics: class varibale
2.1.5 :002 > Car.electronics_controlling? => true
So are two kind of varibales just dirrerent to each other in syntax? It's not exactly. Let define a BMW class inherited from Car
class Car ... @engine = "Diesel" @@automative_electronics = true ... end class BMW < Car @engine = "Hybrid" @@controlling = "Electronics" end puts "#{Car.engine} vs #{ BMW.engine}" puts "#{Car.controlling} vs #{BMW.controlling}"
And this's result when running class above
Diesel vs Hybrid Electronics vs Electronics
It's clear that @engine only has effect inside clas and it'll be changed in different class. Meanwhile, @@controlling is shared between parent class and its subclasses and as a consquence, RClass need to store both these two kind of variables
Methods class
I guess that all of us has the main concept of class methods and object method. On the previous part, we can see that RClass create methods for object by methods table. So where does Ruby keep class method? Let try with an IRB session
2.1.5 :001 > ObjectSpace.count_objects[:T_CLASS] => 887 2.1.5 :002 > class Toyota; end => nil 2.1.5 :003 > ObjectSpace.count_objects[:T_CLASS] => 889
I used ObjectSpace to count all of available clases but there're something abnormal in here. We created just one class named Toyota but 2 more classes were added to :T_CLASS. The answer is Ruby automatically added an additional metaclass which store class methods of Toyota class. However, we cannot see this metaclass by normal way.
2.1.5 :007 > Toyota.singleton_class => #<Class:Toyota> Toyota.singleton_class.methods => [:nesting, :constants, :allocate, ...]
4. The bottom line
This post is quite longer so I really want to say "Thank you" for anyone scrolling to this line. I hope that my post will help all of you to get insights into Ruby clasess and objects.