Reputation: 19767
The following code works:
class MyClass
def method_a
method_b
end
private
def method_b
puts "Hello!"
end
end
m = MyClass.new
m.method_a
Changing the call to method_b to self.method_b
however does not work:
def method_a
self.method_b
end
I get a NoMethodError
. I'm under the impression that self
just resolves to the instance of the class when inside an instance method. Why does self.method_b
cause problems?
Note: self.method_b
works when private
is changed to protected
.
Note: if the above methods are changed to class methods then calling self.method_b
from method_a doesn't throw the NoMethodError
.
Upvotes: 1
Views: 469
Reputation: 303549
This is how private
methods work in Ruby. They cannot be called with an explicit receiver (unless it is a setter method; see below).
Read more in the section on Access Control from the Pickaxe.
Private methods whose names end with an =
may be invoked using self.method_name = ...
as this is necessary to differentiate them from setting a local variable:
class Foo
def try
set_foo(1) # Invokes private method
self.set_foo(2) # ERROR: private method `set_foo' called for ...
self.send(:set_foo,3) # Invokes private method
bar = 1 # Sets local variable
self.bar = 2 # Invokes private method
self.send(:bar=,3) # Invokes private method
end
private
def set_foo(v)
@foo = v
end
def bar=(v)
@bar = v
end
end
Foo.new.bar = 42 # ERROR: private method `bar=' called for ...
Upvotes: 4
Reputation: 160321
That's just how Ruby works: when you provide an explicit object reference, NoMethodError
is raised to show the code is breaking intent. You could do a self.send
and it would work.
Without the explicit reference, Ruby doesn't do the same visibility check; see this and/or this for a bit more detail.
Nutshell is that private methods can't be called with an explicit receiver, even if it's self
.
Upvotes: 3