On 9/20/06, Ola B. [email protected] wrote:
envision
other object that implements the same interface, regardless of whether
The problem with “just use it”, is that you will have no control over
error handling in this case. In most situations, the error is the
programmers, in which case it doesn’t matter, but when reading in
something you’re not entirely sure what it is, it’s better to be able to
report consistently what’s wrong to the user instead of failing randomly
with a method_missing in the middle of nowhere.
If you were just moving there error check earlier, by using respond_to?,
I
think this would be fine. The problem I have with what you did is that
you
are also checking “class”. The only example I saw checked that the
argument
was a Hash. On top of that you state that you want some type of static
type
checking in the language. That is clearly not duck typing.
Describing the “duck type” of something can be quite difficult. In
addition
to describing what it responds to, you’ll need to recursively describe
the
“duck type” of the arguments and return value of those methods. And
then
if the thing is stored in an instance variable (or class or global)
you’ll
need to know how it will eventually get used.
If you wanted checking ahead of time, I think the best thing would be to
analyze the code and figure all of the out. You might even find errors
at
this point, but ruby’s dynamic nature may make this difficult.
I think an unfortunate thing about the term “duck typing” is that it has
multiple meanings. If you look in the pickaxe book, the “Duck Typing”
chapter presents several concepts which people can claim to be “duck
typing”:
-
don’t worry about the type of an object. Just use its methods and
assume
whoever made the object has those capabilities. You’ll get a method
missing
error if it doesn’t have those methods. This is the primary definition
I
use. I think a “duck type” in this context is analogous what C++ STL
calls
a “concept” - which is only described in documentation (for now at
least). -
use respond_to? ahead of time to check the object instead of waiting
for
a method missing error. This is discouraged though as it creates code
bloat. -
“the type of an object is defined by what that object can do. In
Ruby,
we call this duck typing. If an object walks like a duck and talks like
a
duck, then the interpreter is happy to treat it as if it were a duck.”
In
the context of the examples surrounding this, I think this means the
same as
#1. But, if you take this out of context, the exact wording of this
looks
to mean the “type” of an object is defined by its entire set of
capabilities. So, 2 objects have the same “type” only if they have the
same
capabilities/methods. So, you have to mimic an entire class to have the
same “type” by this definition. So, you might say that StringIO has the
same type as IO - but even this falls short as there are a few
differences
in capabilities. I’m not where this concept of “type” in ruby is
useful. -
multimethods based on an object’s capabilities. The example given is
for
File.new where it can either take something responding to #to_int
(taking
the result as a file descriptor) or something to #to_str (taking it as a
filename). I think it is better to simply define different methods.
With
the multimethod approach you have to be careful which methods you use to
choose with, as some objects you want to use may have methods for
multiple
cases. For example, you define a method called “go” that will either
cause
its argument to “fly”, “walk”, or “swim” depending on which of those
methods
it responds to. What if you give this method a duck which happens to do
all
3? Ambiguity. -
using conversion methods: #to_. At first, this looks like just a
special case of #1 - you can use these take any argument that responds
to
some #to_ method. You need to look one level deeper though - at what
is
returned by this method. For most cases, it ends up just being static
typing with a convenient conversion layer to that static type (exact
class). For example, the #to_str method has to typically return a
String,
not an object that responds to some subset of methods of String.
No wonder people have so many concepts for “duck typing”. I think it
was a
mistake to make the title of this chapter “Duck Typing”. It should have
been more generic. I’ve seen people on ruby-talk use each of these
concepts
to mean “duck typing” - plus others.