Because Ruby is dynamically typed,
respond_to? is an important method. Although sometimes
is_a? will creep into code,
respond_to? should always be considered first.
def my_method(input)
input.quack if input.is_a?(Duck)
end
def my_method(input)
input.quack if input.respond_to?(:quack)
end
We don't care if it's a duck, we only care if it quacks.
A problem arises when developers start to use
method_missing to implement methods. Let's say a developer did something like this:
class Duck
def method_missing(method, *args, &block)
if method.to_s =~ /^quack/
puts "quack!"
else
super
end
end
end
For arbitrary rationale, this would allow the duck to quack any of the following ways:
duck.quack
duck.quack!
duck.quack_loudly
However, we've created a problem with
respond_to?.
duck.respond_to?(:quack)
duck.quack
We have now limited our ability to use dynamic typing. We cannot depend on
respond_to? telling us if our object can quack. Therefore, when using
method_missing, remember to update
respond_to?
class Duck
QUACK_METHOD = /^quack/
def respond_to?(method)
return true if method =~ QUACK_METHOD
super
end
def method_missing(method, *args, &block)
if method.to_s =~ QUACK_METHOD
puts "quack!"
else
super
end
end
end
Although
method_missing can still be problematic, this makes it a little less painful.