Ruby as an Object Oriented Language. What that means is whatever message I send, I strictly send it on some object/instance of class.
Example:
class Test
def test1
puts "I am in test1. A public method"
self.test2
end
def test2
puts "I am in test2. A public Method"
end
end
makes sense I call method test2
on self
object
But I cannot do this
class Test
def test1
puts "I am in test1. A public method"
self.test2 # Don't work
test2 # works. (where is the object that I am calling this method on?)
end
private
def test2
puts "I am in test2. A private Method"
end
end
When test2
is public method
I can call it on self
(fair enough, a method sent to self object). But when test2
is private method
I cannot call it on self. So where is the object that I am sending method on?
self
means the current instance of the object you are in.Calling
Test.new.test1
will return something like#<Test:0x007fca9a8d7928>
.This is the instance of the Test object you are currently using.
Defining a method as private means it can only be used inside the current object.
When using
self.test2
, you are going outside of the current object (you get the instance) and you call the method.So you are calling a private methods as if you were not in the object, which is why you can't.
When you don't specify
self
, you remain inside the current object.So you can just call the method. Ruby is smart enough to know that
test2
is a method and not a variable and to call it.The Problem
In Ruby, private methods can't be called directly with an explicit receiver; self doesn't get any special treatment here. By definition, when you call
self.some_method
you are specifying self as the explicit receiver, so Ruby says "No!"The Solution
Ruby has rules for its method lookups. There may be a more canonical source for the rules (other than going to the Ruby source), but this blog post lays out the rules right at the top:
In other words, private methods are first looked up in self without requiring (or allowing) an explicit receiver.
It's
self
. Whenenver you don't specify a receiver, the receiver isself
.The definition of
private
in Ruby is that private methods can only be called without a receiver, i.e. with an implicit receiver ofself
. Interestingly, it didn't bother you at all with theputs
method which is also a private instance method ;-)Note: there's an exception to this rule. Private setters can be called with an explicit receiver, as long as the receiver is
self
. In fact, they must be called with an explicit receiver, because otherwise there would be an ambiguity with local variable assignments: