Mariusz Pekala
6/1/2007 12:58:00 PM
On 2007-06-01 19:33:03 +0900 (Fri, Jun), Vin Raja wrote:
> 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???
While waiting for someone wiser than me to answer, I'll try to explain
how I understand it :-)
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.
--
No virus found in this outgoing message.
Checked by 'grep -i virus $MESSAGE'
Trust me.