rubyselfinstancesinstance-methods

Why do Ruby instance method invocations behave differently when prefixed with 'self'?


The two invocations of an instance method carry different semantics. The first call to bar works as expected.

class T
  def foo
    bar      # <= This works. "bar" is printed.
    self.bar # <= EXCEPTION: `foo': private method `bar' called for ...
  end

  private

  def bar
    puts 'bar'
  end
end

t = T.new
t.foo

I'd like to understand why. What causes self.bar to have a different semantics, throwing an exception? I'm not interested in the exception per se since I can work around with the dubious removal of the private label, but primarily interested in the semantic discussion.


Solution

  • Private methods can not be called with explicit receiver like self. This means that you can call a private method from within a class it is declared in as well as all subclasses of this class.

    Here is a good article about that. It explains well why code like yours will raise NoMethodError.

    On wikibooks there is also a good explanation of visibility levels in ruby.

    For the reference you can bypass this with Object#send but generally it is considered as a bad practice to do so.