Private methods - only available to oneself?

Hi, all.

I'm a somewhat newbie in ruby realm, and trying to write some codes.
Yesterday, I've found very strange characteristics in ruby.

Please see the following:

irb(main):001:0> class Foo
irb(main):002:1> private
irb(main):003:1> def bar
irb(main):004:2> print "hi"
irb(main):005:2> end
irb(main):006:1> end
=> nil
irb(main):007:0> class Foo
irb(main):008:1> public
irb(main):009:1> def duh
irb(main):010:2> f = Foo.new
irb(main):011:2> f.bar
irb(main):012:2> end
irb(main):013:1> end
=> nil
irb(main):014:0> f = Foo.new
=> #<Foo:0x2cdd2f0>
irb(main):015:0> f.duh
NoMethodError: private method `bar' called for #<Foo:0x2cdb7a8>
        from (irb):11:in `duh'
        from (irb):15
irb(main):016:0> quit

As you can see in the above, method "bar" is private to Foo. And that
method is called from another public method "duh". "duh" calls private
method of "f", which is not the instance where "duh" is called.

In all other languages, such as Java and C++, it is perfectly legal to
call private method as long as the method is called from methods of
the same class.

For example, the following complies in C++:

#include <iostream>

using namespace std;

class Foo
{
    private:
        void foo()
        {
            cout << "hi" << endl;
        }

    public:
        void duh()
        {
            Foo f;
            f.foo();
        }
};

int main()
{
    Foo f;
    f.duh();
    return 0;
}

I'm not saying that Ruby is wrong while the others are correct. I'm
just trying to figure out the "reason" of this strange behavior. Any
one can tell me?

The short answer would be: because Ruby is not Java or C++.
The long answer is: in Ruby you can't invoke private methods by using
explicit receiver:

irb(main):001:0> class A
irb(main):002:1> def m; puts 'ok' end
irb(main):003:1> private :m
irb(main):004:1>
irb(main):005:1* def test
irb(main):006:2> m
irb(main):007:2> self.m
irb(main):008:2> end
irb(main):009:1> end
=> nil
irb(main):010:0> A.new.test
ok
NoMethodError: private method `m' called for #<A:0x3331d0>
        from (irb):7:in `test'
        from (irb):10
irb(main):011:0>

Kent.

···

from :0

On 2/11/06, minkoo.seo@gmail.com <minkoo.seo@gmail.com> wrote:

Hi, all.

I'm a somewhat newbie in ruby realm, and trying to write some codes.
Yesterday, I've found very strange characteristics in ruby.

Please see the following:

irb(main):001:0> class Foo
irb(main):002:1> private
irb(main):003:1> def bar
irb(main):004:2> print "hi"
irb(main):005:2> end
irb(main):006:1> end
=> nil
irb(main):007:0> class Foo
irb(main):008:1> public
irb(main):009:1> def duh
irb(main):010:2> f = Foo.new
irb(main):011:2> f.bar
irb(main):012:2> end
irb(main):013:1> end
=> nil
irb(main):014:0> f = Foo.new
=> #<Foo:0x2cdd2f0>
irb(main):015:0> f.duh
NoMethodError: private method `bar' called for #<Foo:0x2cdb7a8>
        from (irb):11:in `duh'
        from (irb):15
irb(main):016:0> quit

As you can see in the above, method "bar" is private to Foo. And that
method is called from another public method "duh". "duh" calls private
method of "f", which is not the instance where "duh" is called.

In all other languages, such as Java and C++, it is perfectly legal to
call private method as long as the method is called from methods of
the same class.

For example, the following complies in C++:

#include <iostream>

using namespace std;

class Foo
{
    private:
        void foo()
        {
            cout << "hi" << endl;
        }

    public:
        void duh()
        {
            Foo f;
            f.foo();
        }
};

int main()
{
    Foo f;
    f.duh();
    return 0;
}

I'm not saying that Ruby is wrong while the others are correct. I'm
just trying to figure out the "reason" of this strange behavior. Any
one can tell me?

Private methods are only callable from within the same objects.
In your, situation, that's not happening. You are calling bar
of one Foo object from another Foo object.

You should use "protected" to "define" that behavior.

See below.

gegroet,
Erik V. - http://www.erikveen.dds.nl/

···

----------------------------------------------------------------

class Foo
protected
   def bar
     puts "hi"
   end
end

class Foo
public
   def duh
     f = Foo.new
     f.bar
   end
end

f = Foo.new
f.duh

f = Foo.new
f.bar # Should fail...

----------------------------------------------------------------

Thanks, Kent.

Yes, I know that Ruby is neither Java nor C++.

Let me put this way. Private methods should be called by an entity
which understand the internals of the object. Also, the entity will be
tightly coupled with the implementaion details.

In the code I've shown above, private method is called by the class
itself. I believe it is manifest that the class itself can not but
coupled with oneself. In addition, it is also sure that the object
understand the internal structure and implementation details.

That being said, is there still any reason to prohibit such a private
method access?

Erik Veenstra wrote:

Private methods are only callable from within the same objects.

It does in Ruby. However, Java and C++ allows that if the method is
called from another method which is public.

class Foo
protected
   def bar
     puts "hi"
   end
end

f = Foo.new
f.bar # Should fail...

I agree with you that this code should fail.

I'm not saying that it's incorrect. I want to find out the reason of
design decision.

Best,
Minkoo Seo

The reason of what design decision?

Ruby doesn't have Java's "public" (anyone may access) and "private"
(same-class only), it has one additional level with better names:

public - anyone may access
protected - same class only, please
private - only from the instance itself

"Mom, my brother is messing with my hair! Protect me!"
"Your hair *is* protected, that's the problem. Make it private and then
he won't be able to touch it."

Thank you Phrongz. Now I understand what Erik said.

Try this:

f = Foo.new
f.instance_eval{bar} # Won't fail... !!!

.... instead of this:

f = Foo.new
f.bar # Should fail...

Just to confuse you...

protected - same class only, please

That's why Phrogz said "please".

private - only from the instance itself

He should have said "please", again.

gegroet,
Erik V. - http://www.erikveen.dds.nl/

Okay. Now I got totally confused. What's the purpose of instance_eval?

> f.instance_eval{bar} # Won't fail... !!!

Okay. Now I got totally confused. What's the purpose of
instance_eval?

Instance_eval evaluates the given block within the context of
the receiver. This means that bar is called from within the
context of f itself.

(You should have asked: "If we can do this, what's the purpose
of 'protected' or 'private'?"...)

gegroet,
Erik V. - http://www.erikveen.dds.nl/

I'm sorry Erik. I'm not native English speaker. So, sometimes it's not
easy to express what I have in my mind in English.

Yes, what I did want to know is "If we can do this, what's the purpose
of 'protected' or 'private'?"

Best,
Minkoo Seo

Thanks, Erik. I'm afraid that I'm not a native English spearker, so
sometimes it's not easy to express my own idea in exact English
expression.

Of course, I did look up the reference and found what instance_eval
does when being called. What I tried to ask was, as you stated,
"If we can do this, what's the purpose of 'protected' or 'private'?"

Thanks in advance.

Best,
Minkoo Seo

I'm sorry Erik. I'm not native English speaker. So, sometimes
it's not easy to express what I have in my mind in English.

I ain't either... :slight_smile:

Yes, what I did want to know is "If we can do this, what's
the purpose of 'protected' or 'private'?"

Good question. I truly don't know the answer.

Matz?

gegroet,
Erik V. - http://www.erikveen.dds.nl/

Minkoo Seo wrote:
...

"If we can do this, what's the purpose of 'protected' or 'private'?"

To let you know when code is being used contrary to its design. The idea is not to make things impossible, but to facilitate intention.

If you unwittingly call a private method, Ruby complains. But if you still believe you have a good reason to call it, Ruby makes it possible.

Ruby assumes the developer is a grown-up.

···

--
James Britt

"Blanket statements are over-rated"

Minkoo Seo wrote:

Thanks, Erik. I'm afraid that I'm not a native English spearker, so
sometimes it's not easy to express my own idea in exact English
expression.

Of course, I did look up the reference and found what instance_eval
does when being called. What I tried to ask was, as you stated,
"If we can do this, what's the purpose of 'protected' or 'private'?"

'private' is not like a locked door. It is like a sign saying "Do Not
Enter.'

Or look at it this way: It makes it "more difficult" to access private
vars (so that you will know you shouldn't), but doesn't make it
impossible (in case you really, really need to).

Hal

I think the purpose of instance_eval is one of those "sharp knife"
things in Ruby. (Some other languages try to protect by not giving you
sharp knives. Ruby gives you sharp knives, and trusts that you know
enough not to hurt yourself.)

In Ruby, you can always use instance_eval to tweak the @instance
variables for an object. Even if 'private' and 'protected' were
enforced, this means that you can totally break the OOP encapsulation.

1) Any time you use #instance_eval, you should say to yourself "Damn,
this is a very sharp knife. I'd better be sure not to cut myself!"
Especially if you're messing wih the internals of a class you don't
know fully how it works.

2) If you are writing a class or module for use by others, they will
have access to the source code, and could rewrite it to allow things
you didn't intend. Use 'protected' and 'private' to indicate when the
methods should be called under normal circumstances. But it's not a
guarantee.

Hal Fulton wrote:

Minkoo Seo wrote:

Thanks, Erik. I'm afraid that I'm not a native English spearker, so
sometimes it's not easy to express my own idea in exact English
expression.

Of course, I did look up the reference and found what instance_eval
does when being called. What I tried to ask was, as you stated,
"If we can do this, what's the purpose of 'protected' or 'private'?"

'private' is not like a locked door. It is like a sign saying "Do Not
Enter.'

Or look at it this way: It makes it "more difficult" to access private
vars (so that you will know you shouldn't), but doesn't make it
impossible (in case you really, really need to).

Hal

I do not understand why within the class definiton the Ruby interpreter
distinguishes between implicit and explict calls to self.

i.e

Class Foo

def foo_one
  bar
end

def foo_two
  self.bar
end

def bar
  puts "In Bar"
end

private :bar

end

f = Foo.new

f.foo_one
-> "In Bar"

f.foo_two
-> NoMethodError: private method `bar' called for

This leads to the inference that self !=== <implicit self> which strikes
me as decidedly odd. Self is either always self or it is not and if not
then what is it? Whether self is declared as the the receiver or left
for the interpreter to contextually establish should make no difference
to the effect of a private method. Is this difference due to a parsing
limitation or a purposeful design decision that serves some intent I
cannot presently fathom? If the latter, then what is the purpose served
by this disticntion between an explicit and implicit self receiver?

···

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

Phrogz wrote:

2) If you are writing a class or module for use by others, they will
have access to the source code, and could rewrite it to allow things
you didn't intend. Use 'protected' and 'private' to indicate when the
methods should be called under normal circumstances. But it's not a
guarantee.

There's a few loopholes around private and protected, e.g. subclass a
class with private methods and declare them public in the subclass, but
one of them is closed in 1.9, you can't #send private methods anymore
(ok, you can #funcall them, ...)

http://eigenclass.org/hiki.rb?Changes+in+Ruby+1.9

Phrogz wrote:

1) Any time you use #instance_eval, you should say to yourself "Damn,
this is a very sharp knife. I'd better be sure not to cut myself!"
Especially if you're messing wih the internals of a class you don't
know fully how it works.

The other main thing to be concerned about when accessing private methods is that their behavior, or even existence, may change in the next version of the class. Furthermore, except for debugging purposes, I'd say that if you find yourself needing to access private class methods from outside the class, it's because the class in question needs a redesign, or has a bug.

That said, I do think that Ruby's decision to make private mean "only accessible to oneself" as opposed to "only accessible to class members" is debatable. In fact I don't see the point of it from a practical point of view. It seems to me that the main reasons for making methods private is advertise that a) they're implementation details that may change without notice in new versions of the class, and b) they may require inside knowledge of the class's workings to use correctly. Both of these reasons would be just as well served by allowing other instances of the same class to access private members, so I don't see the point of the extra restriction. Anyone?

Adam

Hi --

Hal Fulton wrote:

Minkoo Seo wrote:

Thanks, Erik. I'm afraid that I'm not a native English spearker, so
sometimes it's not easy to express my own idea in exact English
expression.

Of course, I did look up the reference and found what instance_eval
does when being called. What I tried to ask was, as you stated,
"If we can do this, what's the purpose of 'protected' or 'private'?"

'private' is not like a locked door. It is like a sign saying "Do Not
Enter.'

Or look at it this way: It makes it "more difficult" to access private
vars (so that you will know you shouldn't), but doesn't make it
impossible (in case you really, really need to).

Hal

I do not understand why within the class definiton the Ruby interpreter
distinguishes between implicit and explict calls to self.

i.e

Class Foo

def foo_one
bar
end

def foo_two
self.bar
end

def bar
puts "In Bar"
end

private :bar

end

f = Foo.new

f.foo_one
-> "In Bar"

f.foo_two
-> NoMethodError: private method `bar' called for

This leads to the inference that self !=== <implicit self> which strikes
me as decidedly odd. Self is either always self or it is not and if not
then what is it? Whether self is declared as the the receiver or left
for the interpreter to contextually establish should make no difference
to the effect of a private method. Is this difference due to a parsing
limitation or a purposeful design decision that serves some intent I
cannot presently fathom? If the latter, then what is the purpose served
by this disticntion between an explicit and implicit self receiver?

I'm mostly guessing, but I imagine because it would be hard to
establish that exception to the rule, and the exception would serve no
purpose. Also, I think of self as a *representation* of the current
object. So when the interpreter sees:

   x

it doesn't literally stick "self" on the front; it just sends the
message to the current object.

David

···

On Sat, 25 Feb 2006, James Byrne wrote:

--
David A. Black (dblack@wobblini.net)
Ruby Power and Light (http://www.rubypowerandlight.com)

"Ruby for Rails" chapters now available
from Manning Early Access Program! Ruby for Rails