Access Modifiers

Hi All
Now another hitch:

1 class Person
2 attr_reader :genre, :style
3 protected :genre
4 private :to_s
5 def psedonym
6 @name
7 end
8
9 def to_s
10 “just another person”
11 end
12 #private :to_s
13 end
14
15 p= Person.new
16 puts p
17 puts “********”
18 puts p.to_s

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
CASE I
With the above class the output comes out to be:

ruby yet.rb
just another person


just another person

CASE II
Now when I comment Line 4 and Uncomment Line 12, the output comes to be:

ruby yet.rb
just another person


yet.rb:18: private method `to_s’ called for just another person:Person
(NoMethodError)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

THE HITCH

In first case it appears that that private declaration had no effect,
thus the textual position matters here; If this is really so, can anyone
explain why??

AND

In second case why the private declaration had no effect on
puts p
when in fact (this is what i infer) it uses the same method which
puts p.to_s
uses.

Can anyone Explain this bias???

Thanks
Raja

On 6/1/07, Vin R. [email protected] wrote:

THE HITCH

In first case it appears that that private declaration had no effect,
thus the textual position matters here; If this is really so, can anyone
explain why??

Note first that private is not a declaration.
It is a method call.

In your case, note that to_s is actually defined on Object already.
In case 1, the to_s inherited from Object is turned private, then gets
overridden.
When you override it, it is no longer private.

In case 2, you override to_s first and then make it private, leaving it
private.

Keep in mind that this happens because you are overriding an existing
method!
You would get different behaviour if it wasn’t an existing method
Play around in irb more :slight_smile:

AND

In second case why the private declaration had no effect on
puts p
when in fact (this is what i infer) it uses the same method which
puts p.to_s
uses.

p doesn’t call to_s. If you look at the docs, it actually calls
Object#inspect
which then uses to_s → which is OK, because they are methods on the
same object!

Kernel.p docs:
http://corelib.rubyonrails.org/classes/Kernel.html#M002080

On 2007-06-01 19:33:03 +0900 (Fri, Jun), Vin R. wrote:

8

Now when I comment Line 4 and Uncomment Line 12, the output comes to be:
In first case it appears that that private declaration had no effect,

Can anyone Explain this bias???

While waiting for someone wiser than me to answer, I’ll try to explain
how I understand it :slight_smile:

In line 4 you change the visibility of existing method to_s.
In line 9 you declare new method with public visibility.
That’s why the line 12 is required to change it back to private.

And why? That’s because in Ruby the definition of your class is not
parsed and then compiled in one step, just it is executed as ordinary
program - each line in your code does something. That’s why the order of
your lines matter - it matters if you first change the visibility of
the method and then define it.

Try to do something like this:

class A
private :non_existing
def non_existing
p ‘in non_existing’
end
end

class B
def non_existing
p ‘in non_existing’
end
private :non_existing
end

In your second topic, the private method to_s may be invoked by not
calling it directly, but by using the ‘send’ hack:
The actual command executed by ‘puts’ is not ‘object.to_s’ but
‘object.send(:to_s)’.

Try something like:

class Person
def to_s
‘bleh’
end
private :to_s
end

puts Person.new.to_s
=> NoMethodError: private method `to_s’ called for bleh:Person

puts Person.new.send(:to_s)
=> “bleh”

The ‘send’ hack allows you to call private methods of any object. To
prevent this you could:

  • make ‘send’ private
    (not recommended, since this would bleak almost everything, I’m
    afraid)
  • override ‘send’ and react when it receives :to_s as parameter.

HTH.