“If it walks like a duck and quacks like a duck, it must be a duck.”
While true, sometimes this must be combined with another epigram to arrive at what Ruby gives you:
“If it walks into a forest and quacks but there’s nobody there to hear it, is it a duck?”
The problem isn’t with duck typing, per se, but in testing the duckiness of an object. Consider a foo object that has a bar method, and a mumble object that also has a bar method. You can define a method that calls bar on an object that’s passed in:
and foo or mumble can be passed in with no ensuing calamity. And happily,
and
return true as expected.
The real fun in Ruby starts when the bar method doesn’t exist in an object, but is created by the method_missing method dynamically. In this scenario, the introspection part of duck-typing can break down.
For instance:
returns false
,
calls fooble
’s bar
, which faults to method_missing, which creates the bar
method in Fooble
and returns whatever the code provided by helper_for(:bar)
returns, and then
returns true
!
This is Lame-Duck Typing. Duck Typing that may not be effective all of the time.
Granted, this is a bit contrived, but in such scenarios testing has to be equally contrived. What it amounts to is a logical race condition. In systems that can create code at run time, introspection can be questionable.
Be careful!