In the previous post, I talked about
this in JS and
self in Ruby.
Everything is an object
Because JS is not like classic OOP, You cannot create another object from the mold(class). Although, it has some similar way(prototype) that you can work like a classic OOP.
Well, I was wrong about
Ruby. There is not such things that you create an object from the definition class. You might heard that
In Ruby, everything is object. I am confused at first. How could it be possible?
class is not an object, you create a thing from the
class that define what properties and methods that a object has. So how could it be possible that
class is an object?
class is an object called
Class. it is different from java or C# that class is a definition
We use the analog that class is
a mold of an object. So mold is also an object.
Let’s start with this easy code:
animal = 'my cat' animal.upcase #MY CAT animal.object_id #8953720 animal.bark #NoMethodError
You assign the string “my cat” to the variable
animal, when you call
animal.upcase, the variable
animal don’t have the methods, so it look right to the class
String, there is an methods named
upcase. And if we call the
object_id method, but it cannot find in the
String class. It then look up at the
Object class. Bingo, it finds the method.
String.ancestors #[String, Comparable, Object, Kernel, BasicObject]
You can check the method-look-up chain of a class in Ruby by calling
ancestors. If a method cannot find, it will go up to search until it hits the
BasicObject. If there is no result there, it will return
NoMethodError. If we draw a diagram here:
So, we can have a little deduction here:
- If we can not find a method, we first go right, then we go up.
- We can think
collective boxof method for an object.
- All the class in Ruby is an object that contains a table of methods.
It is object-oriented, not class-oriented programming
Actually, Ruby knows nothing about the classes, and has no idea on it If you look up the
RDoc, you read the first line in
Classes in Ruby are first-class objects—each is an instance of class Class.
So it is the instance of class
Class. For example,
String.class => Class. It means class
String is an instance of
class Animal end MyCat = Animal.new
Animal.newis called to create a new object, the
new methodin Class is run by default.
Give an object a method
Now, we give
my cat with some action:
def animal.speak puts 'meow' end animal.speak # meows => nil
my cat with the ability to
So the same here. Ruby search if there is a method in the
my cat? No. Is there a
String ? No. Where is the method ?
When you find a method in Ruby, first go to the right, then go up.
Ruby would not want you to see this
class, so we call it
ghost class, some people will call it
meta class or
singleton class. the
speak method is hiding here.
animal.class # => String
See? you can not access this
ghost class , if you call the
class on the object.
Let us recap here:
if you invoke speak method, ruby go right to search for it, but it couldn’t find one, so it simply insert the class of that animal object that contains this speak method. We create a thing here that the class pointer of our animal to be that thing.
class << animal puts self def climb puts 'I can climb' puts self end end animal.climb # I can climb => nil
Uhh… What’s going on here? That is another way you give an object a method. In the
line 2, if you puts out the
self here, as soon as you define the
ghost class, it will execute
It tells you that
self here is
#<Class:#<String:0x00>>. And if you
puts self inside the
climb method, it tell you that
self here is the object “my cat”.
You might already have known that
self in the Ruby will change when you
define the class. But It also change when you make a method invoking.
class D def one_method @a = 1 two end def two_method puts @a end def three_method puts self end end d_object = D.new # self is set to the d_object d_object.one_method # we don't change self here(it is the same, self point to d_obejct, ruby search from two method of the d_object) d_object.three_method #<D:0x00000001183d68> => nil. self now point to the D class.
animal as a receiver, and set
self to be the receiver. Before anything going to happen, Ruby set
self to “my cat” object. Ruby then looks for the method at the method-look-up chain. After execution,
self pop back to the original state.
It comes down to the fact that all Ruby code is executed code–there is no separate compile or runtime phase. In Ruby, every line of code is executed against a particular self.
puts self class Matz puts self end puts self # main # Matz # main
- every line is executable, even when in class definition
selfcan change when method calling.
Do you know how to define a
class Matz def self.speak puts "I can speak Japanese" end end Matz.speak
Easy! Just like that.
self here set to the
Matz. So If we define a class method. That’s how we do it. But by now, you already have known something:
classis an object of
- There is no such things about class.
So Just like
singleton class, Ruby goes right and builds the
ghost class and it finds the
speak method there. So
Matz.speak can prints out “I can speak Japanese.”
So you can also define:
class Matz class << self def speak puts "I can speak Japanese" end end end Matz.speak
Now we know that
<< (less than less than) open up the
ghost class, then we can dump the methods into it.
Almost every beginner in Ruby have some issue with the following code:
class Matz @home = "Japan" def gohome @home end end m = Matz.new p m.gohome # => nil
There is a bug in Ruby? why
nil ? Because
instance variable are always set to
self in line 2 is set to the
class object. In the line 5,
self here is set to the
m object. And they are totally different object. So you can not access the instance variable of the
class Matz @home = "Japan" def self.gohome @home end end p Matz.home # => "Japan"
class Matz @home = "Japan" class << self attr_accessor :home end end p Matz.home # => "Japan" Matz.home = "US" p Matz.home # => "US"
That’s it. That’s what Ruby talk about
everything is an object. And it is the object-oriented programming.