Private methods - only available to oneself?


#1

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:induh’
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

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?


#2

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:intest’
from (irb):10
from :0
irb(main):011:0>

Kent.


#3

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?


#4

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…


#5

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.”


#6

Thank you Phrongz. Now I understand what Erik said.


#7

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/


#8

Erik V. 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 S.


#9

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/


#10

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 S.


#11

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 S.


#12

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


#13

Minkoo S. 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 B.

“Blanket statements are over-rated”


#14

Minkoo S. 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


#15

Hi –

On Sat, 25 Feb 2006, James B. wrote:

‘private’ is not like a locked door. It is like a sign saying "Do Not
distinguishes between implicit and explict calls to self.
self.bar
f = Foo.new
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


David A. Black (removed_email_address@domain.invalid)
Ruby Power and Light (http://www.rubypowerandlight.com)

“Ruby for Rails” chapters now available
from Manning Early Access Program! http://www.manning.com/books/black


#16

James B. wrote:

Hal F. wrote:

Minkoo S. 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.

Think of the self.foo call just accessing an object called
‘self’–sure, it is actually the same object, but you could
just as well replace ‘self’ with the external variable name.
You are still sending a message to an explicit receiver, which
is not possible in Ruby for any private methods (except for the
self.foo = 5, where it is required).

<snip, rforum />

E


#17

Hal F. wrote:

Minkoo S. 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 !=== 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?


#18

E. Saynatkari wrote:

Think of the self.foo call just accessing an object called
‘self’–sure, it is actually the same object, but you could
just as well replace ‘self’ with the external variable name.
You are still sending a message to an explicit receiver, which
is not possible in Ruby for any private methods (except for the
self.foo = 5, where it is required).

Which is why I do not understand the purpose of the distinction between
implicit and explict self. Both cases are simply references. Why does
the interpreter not simply check the reciever object id for === self
when accessing private methods? Where the context cannot determine
intent with resict to assignment (ie foo = “value” is a variable
reference but self.foo = “value” is a call to private method foo=) then
self obviously must be provided, but why must it NOT be provided
otherwise? This makes no sense to me unless it is due a parsing or
other implementation limitation of the interpreter.

If that is the case, well then so be it. What I am interested in
discovering is whether or not their exists a lexical or grammerical
reason for why self is not permitted as an explicit receiver for private
methods except for cases of foo=, where it is then required.

Regards,
Jim


#19

James B. wrote:

E. Saynatkari wrote:

Think of the self.foo call just accessing an object called
‘self’–sure, it is actually the same object, but you could
just as well replace ‘self’ with the external variable name.
You are still sending a message to an explicit receiver, which
is not possible in Ruby for any private methods (except for the
self.foo = 5, where it is required).

Which is why I do not understand the purpose of the distinction between
implicit and explict self. Both cases are simply references. Why does
the interpreter not simply check the reciever object id for === self
when accessing private methods? Where the context cannot determine
intent with resict to assignment (ie foo = “value” is a variable
reference but self.foo = “value” is a call to private method foo=) then
self obviously must be provided, but why must it NOT be provided
otherwise? This makes no sense to me unless it is due a parsing or
other implementation limitation of the interpreter.

Conceptually, self.foo= should not require the ‘self’ part but it
is present for the sole benefit of the parser/lexer.

So, ‘self’ is an external reference to ‘this object’.

If that is the case, well then so be it. What I am interested in
discovering is whether or not their exists a lexical or grammerical
reason for why self is not permitted as an explicit receiver for private
methods except for cases of foo=, where it is then required.

Regards,
Jim

E


#20

James B. wrote:

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

Possibly because it allows you[1] to examine the code and statically
determine if a private method is allowed. If the implicit receiver rule
were not used, then is the following a valid use of a private method?

def f(other)
other.private_method
end

Well, maybe or maybe not. It depends how it is called.

f(self) # private method inside of f is ok
f(you) # private method inside of f is probably not ok,
# (but it really depends on the value of you, doesn’t it)

By using the implicit receiver rule, we know for sure that calling
“private_method” in f is not ok. Less ambiguity.

BTW, the Eiffel language also uses instance based protection (like Ruby)
and also uses the implicit receiver rule as well. So there is
precedent.


– Jim W.