Implicit vs explicit self in private methods

I’m trying to understand the difference between implicitly and
explicitly calling a private method and am hoping someone could shed
some light on this for me.

class Tester
def public_hello_good
say_hello
end
def public_hello_bad
self.say_hello
end
private
def say_hello
“hello”
end
end

irb(main):001:0> require ‘tester’
=> true
irb(main):002:0> a = Tester.new
=> #Tester:0x8c294
irb(main):003:0> a.public_hello_good
=> “hello”
irb(main):004:0> a.public_hello_bad
NoMethodError: private method say_hello' called for #<Tester:0x8c294> from ./tester.rb:6:inpublic_hello_bad’
from (irb):4
from :0

What I’m wondering is why does this not work when I call
self.say_hello, but does work when I call say_hello? Since self is
the receiver in both cases, it seems that they would both work.

Anyone have any insight that they’d be willing to share on why it
works like that?

Thanks

On Sunday 29 June 2008, dusty wrote:

end
irb(main):003:0> a.public_hello_good

Anyone have any insight that they’d be willing to share on why it
works like that?

Thanks

It’s at the same time quite simple and quite confusing. It’s simple
because
the rule determining how a private method can be called is very short
and
clear: you can only call a private method using the implicit receiver.
It’s
confusing because it seems natural to interpret the previous statement
so that
it reads: you can only call a private method if the receiver is equal
(in the
eql? sense) as the implicit receiver. However, this interpretation is
wrong.
The words “only using the implicit receiver” should be taken literaly:
if a
method is private, you can’t call it using the dot notation
(receiver.method_name), even when the implicit and the explicit receiver
are
the same thing.

I hope this helps

Stefano

Hi –

On Mon, 30 Jun 2008, Stefano C. wrote:

self.say_hello

=> #Tester:0x8c294
the receiver in both cases, it seems that they would both work.
it reads: you can only call a private method if the receiver is equal (in the
eql? sense) as the implicit receiver. However, this interpretation is wrong.
The words “only using the implicit receiver” should be taken literaly: if a
method is private, you can’t call it using the dot notation
(receiver.method_name), even when the implicit and the explicit receiver are
the same thing.

Unless it ends in = :slight_smile:

David

On Jun 29, 3:19 pm, Stefano C. [email protected] wrote:

say_hello

irb(main):001:0> require ‘tester’

the rule determining how a private method can be called is very short and

Stefano

Thanks for the response.

I did find that it does work with an explicit receiver on a setter.
In the case below, I can call the private hello= method, with
self.hello=. I know that is required to state that I’m not setting a
local variable, but instead calling a method. But, it did work, so
somewhere in the code it is reading that self and understanding what I
mean by it, then perhaps dropping it and following the rules for the
rest of it?

I guess I don’t really need to know why, just understand that it is
what it is. Perhaps the why is outside my scope of understanding
right now anyway. But, I am still curious.

:slight_smile:

class Tester
def public_hello_good
say_hello
end
def public_hello_bad
self.say_hello
end
def public_set_hello(hello)
self.hello = hello
end
def hello
@hello
end
private
def say_hello
“hello”
end
def hello=(hello)
@hello = hello
end
end

irb(main):022:0> a = Tester.new
=> #Tester:0x53728
irb(main):023:0> a.public_set_hello(“asdf”)
=> “asdf”
irb(main):024:0> a.hello
=> “asdf”

Hi –

On Mon, 30 Jun 2008, dusty wrote:

def public_hello_good

from :0
It’s at the same time quite simple and quite confusing. It’s simple because
I hope this helps
mean by it, then perhaps dropping it and following the rules for the
rest of it?

I guess I don’t really need to know why, just understand that it is
what it is. Perhaps the why is outside my scope of understanding
right now anyway. But, I am still curious.

I think it’s just a necessary compromise. The local assignment syntax
can’t really change in a private method, so the only thing left is the
explicit receiver. It does make the private rule a bit more tricky but
in practice it ends up being OK.

David