Top Level Private Methods
In this chapter, you will learn how the top level context and private methods work together.
Implicit Receiver
Let's print hello in the standard output.
puts 'hello'
As expected, this prints:
hello
Explicit Receiver
If you use an explicit receiver, the self to call the puts:
self.puts 'hi'
We get:
NoMethodError: private method ‘puts’ called for main:Object
This is because puts is a private method in Object. In Ruby you cannot have an explicit receiver to call a private method. Why? Because, when the sender and receiver are the same, you cannot use an explicit receiver to send a message.
The Kernel Module
Where does the private method puts() live? Let's search for methods that begin with put.
Kernel.methods.grep(/put/)
This prints:
[:putc, :puts]
It lives in Kernel module. Ruby mixes in the Kernel module into the Object class. That's how it is available as a private method on the Object.
Private Method and Explicit Receiver
How do we grab the main, the top level default object? Let's grab the value of the current object from the self and assign it to our own variable m.
m = self
m.puts 'hi'
We get the same error message as we did in step 2.
NoMethodError: private method ‘puts’ called for main:Object
Why do we get this error? You can think of the code that gives error to be equal to this:
class Object
private
def puts(arg)
# Implementation for printing to standard output
end
end
We cannot call the puts private method with an explicit receiver.
Forcing an Explicit Receiver
We can use send() method to send the puts() message to the main object:
m = self
m.send(:puts,'hi')
This will work. This is the same as:
self.send(:puts,'hi')
But, this breaks encapsulation and is generally not a good idea unless you have a good reason to do so.
Using Method Object
We can also do this:
m = self.method(:puts)
=> #<Method: Object(Kernel)#puts>
> m.call('hello')
hello
=> nil
You can see how using the method object displays the relationship between the Kernel module and Object class. The puts() method is available by mixing in the Kernel module into the Object class.
Summary
In this chapter we saw how the private methods and the top level context work together. The concept you learned in the previous chapter is a generalized concept of the concept in this chapter.