Puts bypasses access restrictions on to_s?

I read somewhere that “puts” calls “to_s” on an object to get a string
representation and then displays that. This seems to be correct in my
experience.

My question is: how does puts bypass “private” restrictions to get the
value of to_s?

See here:

irb(main):005:0> class RiseAndShine
irb(main):006:1> private
irb(main):007:1> def to_s
irb(main):008:2> “rising and shining”
irb(main):009:2> end
irb(main):010:1> end
=> nil
irb(main):011:0> rs = RiseAndShine.new
=> rising and shining
irb(main):012:0> rs.to_s
NoMethodError: private method `to_s’ called for rising and
shining:RiseAndShine
from (irb):12
irb(main):013:0> puts rs
rising and shining
=> nil
irb(main):014:0>

On Sat, 29 Jul 2006, Leslie V. wrote:

=> rising and shining
irb(main):012:0> rs.to_s
NoMethodError: private method `to_s’ called for rising and
shining:RiseAndShine
from (irb):12
irb(main):013:0> puts rs
rising and shining

irb(main):008:0> rs.send(:to_s)
=> “rising and shining”

Ruby lets private be circumvented.

To see how puts really works, though, take a look at the source code.
It’s pretty easy to read. Look in io.c for rb_io_puts(). Start from
there.

Kirk H.

On 28/07/06, Leslie V. [email protected] wrote:

I read somewhere that “puts” calls “to_s” on an object to get a string
representation and then displays that. This seems to be correct in my
experience.

My question is: how does puts bypass “private” restrictions to get the
value of to_s?

Interesting question. I had a look at the C source, and it uses
rb_funcall, which doesn’t check private/protected, to call to_s.

If you want to do the same thing, you can use this:
rs.send(:to_s)

Paul.

On 7/29/06, Paul B. [email protected] wrote:

If you want to do the same thing, you can use this:
rs.send(:to_s)

That seems wrong! Not that you can bypass access restrictions, which I
think you can do in many languages, but that ‘puts’ does so. Though
OTOH I’m sure there’s a very good argument for ‘puts’ being
high-speed.