[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Private methods - only available to oneself?

minkoo.seo@gmail.com

2/11/2006 5:26:00 AM

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?

49 Answers

Kent Sibilev

2/11/2006 6:18:00 AM

0

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

Kent.

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?
>
>
>


minkoo.seo@gmail.com

2/11/2006 8:57:00 AM

0

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

2/11/2006 9:39:00 AM

0

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

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

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

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

minkoo.seo@gmail.com

2/11/2006 9:50:00 AM

0

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

Gavin Kistner

2/11/2006 10:24:00 AM

0

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

minkoo.seo@gmail.com

2/11/2006 10:59:00 AM

0

Thank you Phrongz. Now I understand what Erik said.

Erik Veenstra

2/11/2006 11:16:00 AM

0

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

minkoo.seo@gmail.com

2/11/2006 11:26:00 AM

0

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

Erik Veenstra

2/11/2006 11:39:00 AM

0

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

minkoo.seo@gmail.com

2/11/2006 12:00:00 PM

0

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