Ducktype, right?

Well, you can always check for more than one method
if you need to call more that one method. There’s
nothing that says that if it walks but doesn’t
quack or act like a duck, that it is a duck.

I think the idea of duck typing is that there is
no real Duck type, formally. Instead of looking at
something’s type to determine whether you can ask
it to do something, you just ask whether it can do
it directly.

This is dangerous, of course, because there’s
nothing that says that fred.sin is the mathematical
sine function or the Biblical sin function.
Responding to a method doesn’t necessarily mean
that it responds in the correct way.

However, if you really think about it, Java doesn’t
guarantee this either. You can make an interface

interface Duck
{
void quack();
}

And I can do:

class MyDuck
{
void quack()
{
System.exit();
}
}

Which isn’t really what’s expected of a Duck quacking.
No amount of checking that something implements a
particular interface tells you that I didn’t do
something stupid, or to deliberately sabotage you.

The only differences between Ruby and Java in this
sense is that Java checks types at compile time, and
Java is more strict in what something of “type Duck”
is. There’s always the potential that someone has
done something stupid, which is why testing is
important.

  • Dan
···

----- Original Message -----
From: Ben Giddings ben@thingmagic.com
Date: Friday, August 8, 2003 1:51 pm
Subject: Re: Ducktype, right?

On Fri August 8 2003 1:25 pm, Dave Thomas wrote:

 fred << "dog"

in Ruby, I don’t care whether fred is a String, a File, or an
Array (a
fact that’s very useful when writing unit tests).

The one thing that I think is underemphasized about the duck
typing concept is
that just because something floats, it might not be a duck (it
might be a
witch!)

In Java you could check to see if something is of a certain class,
but what
was more often done was to see if something implemented a certain
interface.
Implementing an interface was a way of signalling “I declare
myself to act
like a duck”. And the fact you implemented the interface meant
that you had
all the necessary features to act like a duck. You weren’t
allowed to
implement the interface and then only choose certain duck-like
features.
It seems to me that duck-typing in Ruby should strive for the same
thing.
Checking for one method isn’t enough, in my opinion.

djd15@cwru.edu writes:

This is dangerous, of course, because there’s
nothing that says that fred.sin is the mathematical
sine function or the Biblical sin function.
Responding to a method doesn’t necessarily mean
that it responds in the correct way.

This might work in some cases:

$DUCK_TESTING = true

def duck_test
return unless $DUCK_TESTING
begin
yield or raise “Looks like you’re using the wrong duck.”
rescue NameError
raise “Looks like you’re using the wrong duck.”
end
end

class Duck
def initialize
@altitude = 0
end

attr_reader :altitude

def float
@altitude += 100
end
end

class String
def float
to_f
end
end

class DuckUser
def use(duck)
duck_test do
d = duck.dup
d.float
d.altitude > 0
end

duck.float
puts "This duck has reached #{duck.altitude}!"

end
end

duck_user = DuckUser.new
real_duck = Duck.new
fake_duck = “0.234”

duck_user.use(real_duck)
duck_user.use(fake_string)

Produces:

This duck has reached 100!
/tmp/ruby276635A:8:in test': Looks like you're using the wrong duck. (RuntimeError) from /tmp/ruby276635A:38:in use’
from /tmp/ruby276635A:51

Of course this relies on the assumption that a method produces a
measurable effect somewhere.