Private and protected

Could anybody explain me this, please?

class First
     def say
         self.phrase
     end

     private

     def phrase
         'something'
     end
end

a = First.new
a.say
# got
NoMethodError: private method `b' called for #<A:0xb7756518>
     from (irb):44:in `say'
     from (irb):52

If i write the same code with 'protected' instead of 'private' I got no error.
If i write the same code with calling 'phrase' instead of 'self.phrase' in 'say' method I got no error again.

···

from :0

The call 'self.phrase' is a call to a class method but 'def phrase' is
the definition of an instance method. Either remove the self in the
say method or change 'def phrase' to 'def self.phrase'.

It has nothing to do with private or protected.

A private method may only be called with an implicit receiver - in
self.phrase, self is explicit, which is why you get the exception. The
practical upshot of this is that private methods may only be called by the
current instance, because the implicit receiver is understood to be "self".

Protected methods may be called by the current instance, instances of its
class or instances of it subclasses, and require an explicit receiver,
except when the receiver is the current instance. I would tend, even then,
to pass it explicitly to help make the code's intent clearer.

This has been expressed much more elegantly in numerous places, so search
the web if I only served to confuse!

Dan

···

On Wed, Nov 23, 2011 at 10:20:54PM +0900, Николай wrote:

Could anybody explain me this, please?

class First
    def say
        self.phrase
    end

    private

    def phrase
        'something'
    end
end

a = First.new
a.say
# got
NoMethodError: private method `b' called for #<A:0xb7756518>
    from (irb):44:in `say'
    from (irb):52
    from :0

If i write the same code with 'protected' instead of 'private' I got no
error.
If i write the same code with calling 'phrase' instead of 'self.phrase'
in 'say' method I got no error again.

--
Daniel Bye
                                                                     _
                                              ASCII ribbon campaign ( )
                                         - against HTML, vCards and X
                                - proprietary attachments in e-mail / \

This isn't correct, it has everything to do with private or protected! The
methods and method calls in the example are all instance methods, not class
methods. self.class.phrase would be a class method call.

As Daniel has said, the "problem" is that private methods may not be called
with an explicit receiver.

···

On Wed, Nov 23, 2011 at 14:08, Peter Hickman <peterhickman386@googlemail.com > wrote:

The call 'self.phrase' is a call to a class method but 'def phrase' is
the definition of an instance method. Either remove the self in the
say method or change 'def phrase' to 'def self.phrase'.

It has nothing to do with private or protected.

The call 'self.phrase' is a call to a class method

I am sorry, this is wrong. A class method would be called with
"self.class.phrase". "self.phrase" attempts to invoke an instance
method.

but 'def phrase' is
the definition of an instance method. Either remove the self in the
say method or change 'def phrase' to 'def self.phrase'.

It has nothing to do with private or protected.

It has:

irb(main):001:0> class First
irb(main):002:1> def say_1; self.phrase; end
irb(main):003:1> def say_2; phrase; end
irb(main):004:1> private
irb(main):005:1> def phrase;"ph";end
irb(main):006:1> end
=> nil
irb(main):007:0> f = First.new
=> #<First:0x10183174>
irb(main):008:0> f.say_1
NoMethodError: private method `phrase' called for #<First:0x10183174>
        from (irb):2:in `say_1'
        from (irb):8
        from /opt/bin/irb19:12:in `<main>'
irb(main):009:0> f.say_2
=> "ph"

See Daniel's explanation.

Kind regards

robert

···

On Wed, Nov 23, 2011 at 3:08 PM, Peter Hickman <peterhickman386@googlemail.com> wrote:

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

Thank you for your answer, saved me from future mistakes.

···

On 23.11.2011 17:12, Daniel Bye wrote:

On Wed, Nov 23, 2011 at 10:20:54PM +0900, Николай wrote:

Could anybody explain me this, please?

class First
     def say
         self.phrase
     end

     private

     def phrase
         'something'
     end
end

a = First.new
a.say
# got
NoMethodError: private method `b' called for #<A:0xb7756518>
     from (irb):44:in `say'
     from (irb):52
     from :0

If i write the same code with 'protected' instead of 'private' I got no
error.
If i write the same code with calling 'phrase' instead of 'self.phrase'
in 'say' method I got no error again.

A private method may only be called with an implicit receiver - in
self.phrase, self is explicit, which is why you get the exception. The
practical upshot of this is that private methods may only be called by the
current instance, because the implicit receiver is understood to be "self".

Protected methods may be called by the current instance, instances of its
class or instances of it subclasses, and require an explicit receiver,
except when the receiver is the current instance. I would tend, even then,
to pass it explicitly to help make the code's intent clearer.

This has been expressed much more elegantly in numerous places, so search
the web if I only served to confuse!

Dan

I stand corrected.

···

On 23 November 2011 14:12, Daniel Bye <ruby@slightlystrange.org> wrote:

On Wed, Nov 23, 2011 at 10:20:54PM +0900, Николай wrote:

Could anybody explain me this, please?

class First
def say
self.phrase
end

private

def phrase
    &#39;something&#39;
end

end

a = First.new
a.say
# got
NoMethodError: private method `b' called for #<A:0xb7756518>
from (irb):44:in `say'
from (irb):52
from :0

If i write the same code with 'protected' instead of 'private' I got no
error.
If i write the same code with calling 'phrase' instead of 'self.phrase'
in 'say' method I got no error again.

A private method may only be called with an implicit receiver - in
self.phrase, self is explicit, which is why you get the exception. The
practical upshot of this is that private methods may only be called by the
current instance, because the implicit receiver is understood to be "self".

Protected methods may be called by the current instance, instances of its
class or instances of it subclasses, and require an explicit receiver,
except when the receiver is the current instance. I would tend, even then,
to pass it explicitly to help make the code's intent clearer.

This has been expressed much more elegantly in numerous places, so search
the web if I only served to confuse!

Dan

--
Daniel Bye
_
ASCII ribbon campaign ( )
- against HTML, vCards and X
- proprietary attachments in e-mail / \

Although, a common workaround if you really need to send an object a
private method (message) is to do it with the Object#send method. So you
could do:

self.send(:phrase), but then again it would be completely useless in
this case because you could do without the receiver altogether.

There's also an Object#pubic_send(:method, *args, &blk) that just works
for public methods.

-Luke

···

--
Posted via http://www.ruby-forum.com/.