I am a new rubier, so i learned ruby from book-of-ruby. I’m confused in
the singleton methods example as below:
class Box
def initialize( aStr ) @msg = aStr
end
def look_inside
puts( @msg )
end
end
starprize = Box.new( “Star Prize” )
create a singleton method
def starprize.congratulate
puts( “You’ve won a fabulous holiday in Grimsby!” )
end
boxes = [Box.new(“box1 is empty”),
Box.new(“box2 is empty”),
starprize,
Box.new(“box3 is empty”)]
boxes.each do |item|
item.look_inside
# test if the congratulate singleton method exists before calling
it
if item.singleton_methods.include?(“congratulate”) then
if item.respond_to?( :congratulate ) then # an alternative test
item.congratulate
end
end
The question is if use “item.singleton_methods.include?(“congratulate”)”
to evaluate, “item.congratulate” will never run as expected, why? In
the same time, “item.respond_to?( :congratulate )” works well then.
#include? needs to be passed a symbol rather than a string, it doesn’t
perform type conversion, so item.singleton_methods has :congratulate in
and
you’re checking for ‘congratulate’ which looks the same but as far as
Ruby’s concerned is something pretty different.
Basically this should work:
if item.singleton_methods.include?(:congratulate)
item.congratulate
end
#include? needs to be passed a symbol rather than a string, it doesn’t
perform type conversion, so item.singleton_methods has :congratulate in and
you’re checking for ‘congratulate’ which looks the same but as far as
Ruby’s concerned is something pretty different.
Yes, IIRC one of the changes between Ruby 1.8 and 1.9 was that lots of
methods that formerly returned strings now returned symbols.
And for the record, if a collection of objects ever doesn’t contain
something you thought it should, you can always print out the
collection to see what it does contain. E.g.