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:in `public_hello_bad'
  from (irb):4

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

···

from :0

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

···

On Sunday 29 June 2008, dusty wrote:

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:in `public_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

Hi --

···

On Mon, 30 Jun 2008, Stefano Crocco wrote:

On Sunday 29 June 2008, dusty wrote:

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:in `public_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

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.

Unless it ends in = :slight_smile:

David

--
Rails training from David A. Black and Ruby Power and Light:
   ADVANCING WITH RAILS July 21-24 Edison, NJ
See http://www.rubypal.com for details and updates!

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"

···

On Jun 29, 3:19 pm, Stefano Crocco <stefano.cro...@alice.it> wrote:

On Sunday 29 June 2008, dusty wrote:

> 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:in `public_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

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, dusty wrote:

On Jun 29, 3:19 pm, Stefano Crocco <stefano.cro...@alice.it> wrote:

On Sunday 29 June 2008, dusty wrote:

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:in `public_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

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

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.

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

--
Rails training from David A. Black and Ruby Power and Light:
   ADVANCING WITH RAILS July 21-24 Edison, NJ
See http://www.rubypal.com for details and updates!