[fundamental] Inside Ruby Objects and Classes
Bài đăng này đã không được cập nhật trong 3 năm
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 valuesklass
: refer toClass
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 varibaleivptr
: 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](https://images.viblo.asia/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.
All rights reserved