Puts bypasses access restrictions on to_s?

L

Leslie Viljoen

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

khaines

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

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 Haines
 
P

Paul Battley

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

Leslie Viljoen

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)

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,528
Members
45,000
Latest member
MurrayKeync

Latest Threads

Top