From: dusty Date: 2008-06-30T04:37:25+09:00 Subject: Re: implicit vs explicit self in private methods On Jun 29, 3:19 pm, 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 > > => # > > irb(main):003:0> a.public_hello_good > > => "hello" > > irb(main):004:0> a.public_hello_bad > > NoMethodError: private method `say_hello' called for # > >    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. :) 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 => # irb(main):023:0> a.public_set_hello("asdf") => "asdf" irb(main):024:0> a.hello => "asdf"