Duck Typing in Ruby
“If it says its a duck…well that’s good enough for me.”
Well, in short, “duck typing” is the idea that the behavior or capabilities of an object should not be determined by the object’s type but rather by the object’s public interface.
Still reading? Alright, I’ll elaborate.
Why call it “duck typing”?
“Duck typing” was coined by Alex Martelli during the delirious months after Y2K as an attempt to explain the fuzzy behavior of dynamic typing. Compared to the concrete type certainty of C++ and Java, dynamic typing meant that programmers never quite knew the exact type of the objects they were using. In response, early converts to dynamic languages attempted to force static typing by incessantly checking an object’s type. Martelli used a simple analogy to dissuade this behavior:
Don’t check whether it IS-a duck: check whether it QUACKS-like-a duck, WALKS-like-a duck, etc, etc, depending on exactly what subset of duck-like behavior you need to play your language-games with.
Examples of “duck typing” in Ruby
In Ruby everything is an Object and nothing is statically typed. Which is to say, in Ruby the type of a variable or a method is never declared but rather defined through behavior. This inherent flexibility is perfect for “duck typing.”
Let’s create two classes,
Dilophosaurus, to illustrate how “duck typing” works in Ruby. We will give the
Duck class instance methods for
Dilophosaurus class will also get a
walk method but it will
kill instead of quack.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
Obviously, a duck and a dilophosaurus are nothing alike (you’ll never convince me that dinosaurs are birds) so Ruby couldn’t possibly confuse an instance of a
Duck with an instance of a
Let’s try it! We can build a small
is_a_duck? method to give us an idea of how Ruby is treating the two instances.
In this first example the
is_a_duck? method simply checks whether the object passed as an argument responds to the
walk method. If it responds to the methods a
Duck instance would respond to then it’s a
Duck. If it walks like a duck…
1 2 3 4 5 6 7 8 9
Dilophosaurus share the public method
walk Ruby simply doesn’t care that the instances come from different classes. For the purposes of
walk both objects can be treated as if they were the same type.
That’s the great power of “duck typing. ” The method
is_a_duck? does not care about the class of its argument and is flexible enough to be used with multiple types of objects as long as that object responds to
But this example is explicitly checking whether an object responds to a method and this seems overly contrived. If Ruby can handle dynamic typing so easily why not try a more realistic example.
Let’s modify the
is_a_duck? method to call the
quack method on whatever is passed as an argument. If it quacks like a duck…
1 2 3 4 5 6 7 8
Not good. Since the
Dilophosaurus instance does not have a public method
quack Ruby throws-up in disgust and the program breaks. A dinosaur cannot quack and a
Dilophosaurus instance should not be treated like a
This might seem like a trivial example but imagine the
is_a_duck? method is buried under thousands of lines of code and executed by a Kafkaesque chain of callback methods. In this nightmare scenario it might be impossible to ensure the
is_a_duck? method is never passed a
Dilophosaurus instance or any other object that does not respond to
That’s the danger of “duck typing”. If you treat all objects with the same public methods as being of the same type you’ll invariably allow an object to pass through that could crash your whole program.
For one last example let’s see how we could simulate static typing in Ruby by explicitly checking the argument’s class to make sure it is a
1 2 3 4 5 6 7 8 9 10
No confusion here. But this type-certainty comes at a cost. The
is_a_duck? method will never work with anything other than
Duck instances and has now become completely inflexible (not to mention unnecessarily verbose). This kind of rigidity goes against Ruby’s core philosophy and is probably best reserved for static typed languages.
Why should I care about “duck typing”
When used cautiously “duck typing” can be an extremely elegant design technique. Allowing the logic of your code to rely solely on public interfaces rather than the underlying objects grants your application an immense flexibility to grow and adapt over time.
But don’t take my word for it. Follow the advice of the always eloquent Sandi Metz:
If every object trusts all others to be what it expects at any given moment, and any object can be any kind of thing, the design possibilities are infinite. These possibilities can be used to create flexible designs that are marvels of structured creativity or, alternatively, to construct terrifying designs that are incomprehensibly chaotic.