The Dynamic Nature of self
In this chapter you will learn how the value of self changes as the program executes.
Car with Drive Method
Let's define a Car class with a drive() method.
class Car
def drive
'driving'
end
end
We can create an instance of the car class and send a message to the car object.
car = Car.new
car.drive
This prints:
driving
The self Before Sending a Message
Let's see the value of self before we send the drive message to car object.
class Car
def drive
'driving'
end
end
car = Car.new
p "Before sending the message, self is : #{self}"
car.drive
This prints:
Before sending the message, self is : main
The self After Sending a Message
Let's see the value of self after we send the drive message to car object.
class Car
def drive
'driving'
end
end
car = Car.new
car.drive
p "After sending the message, self is : #{self}"
This prints:
After sending the message, self is : main
The self During Message Send
Let's check the value of self during the message send.
class Car
def drive
'driving'
end
end
car = Car.new
car.tap { |x| p "The value of self is : #{x}"}.drive
This prints:
The value of self is : #<Car:0x007fc6bb912d08>
The value of self is the same as the car object.
Rhonda Asks
Where is the tap method defined?
Let's find out.
p Object.method(:tap)
This prints:
#<Method: Class(Kernel)#tap>
The tap method is in the Kernel module.
> Kernel.methods.grep(/tap/)
=> [:tap]
Kernel is mixed in to Object.
> Object.methods.grep(/tap/)
=> [:tap]
Thus, tap method is available on any object. It executes a code block, yielding the receiver to the block and returns the receiver.
Fabio Asks
Why does the following code print main, when I change code ?
car.tap { |x| p "The value of self is : #{self}"}.drive
The self printed inside tap is the same value of self as in the line above the tap call. This is due to closure in Ruby. You will learn about closures in a later chapter. You must print the block variable, if you want to peek inside the car object. We can verify it.
class Car
def drive
'driving'
end
end
car = Car.new
car.tap { |x| p "The value of self is : #{x}"}.drive
p car
This prints:
"The value of self is : #<Car:0x007f854b141ea0>"
#<Car:0x007f854b141ea0>
The memory address of self and the car object is the same. Thus, they are the same object.
The diagram illustrates the value of self before, during and after executing the drive method.
Rhonda Asks
What is self ?
The self refers to the object inside which the current method is executing. It is the receiver of the current executing method.
Summary
In this chapter, you learned that Ruby changes the value of self as it executes the program. There is always a self. The value of self changes to the current executing object and Ruby sends a message to that object. Once the method completes the execution, the value of self changes again. You know that self cannot be assigned any value to it. But you can use language constructs such as class, module and method declarations to make Ruby change the value of self. We will discuss this in the next chapter.