What is duck typing?
I found that when I started dabbling in Python that it was a bit hard to get a grasp on what duck typing actually is. You hear that it achieves polymorphism without inheritance, but that really explains very little. I have a C++/Java/C# background and it took a bit of time before that wonderful epiphany came, where all of a sudden I seemed to get a good grasp on what the concept actually is.
From the Duck typing article on Wikipedia we find that the term comes from the phrase "If it walks like a duck and quacks like a duck, I would call it a duck."
That makes perfect sense now, but it definitely didn't help further my understanding when I first came across it.
Perhaps the best way to explain would be with some code. I'm using Java here because it's wordy enough that it's understandable even if you don't know the syntax. For this "real world" example we will be designing that ever so classic "real world application of object oriented programming": the hierarchy of vehicles.
So suppose we have an existing Driver
class that will drive our vehicles for us, as long as we provide the gas()
, brake()
, turnLeft()
and turnRight()
methods. In Java this would likely be expressed as an interface:
public interface IDriveable { public void gas(); public void brake(); public void turnLeft(); public void turnRight(); }
And then we would have a class that implements that interface, for example:
public class Car implements IDriveable { public void gas() { System.out.println("Vroom vroom"); } public void brake() { System.out.println("Screeeechhhh!"); } public void turnLeft() { System.out.println("Left"); } public void turnRight() { System.out.println("Right"); } }
And the Driver
class would be similar to:
public class Driver { public void drive(IDriveable vehicle) { vehicle.gas(); vehicle.turnLeft(); vehicle.brake(); } }
And the main class:
public class Start { public static void main(String[] args) { Car c = new Car(); Driver d = new Driver(); d.drive(c); } }
Sample output:
Vroom vroom Left Screeeechhhh!
This is standard OOP stuff, where as long as our class implements the IDriveable
interface, it'll be driveable by the Driver
class. If the class does not implement that interface, the code will not even compile.
If we bring duck typing into the picture, things change. Instead of having a defined interface (IDriveable
) which must be implemented, all we require is that a given class implements the specific methods needed. There is no strict interface. In Python our code would look like:
class Car: def gas(self): print "Vroom vroom" def brake(self): print "Screeeechhhh!" def turnLeft(self): print "Left" def turnRight(self): print "Right" class Driver: def drive(self, vehicle): vehicle.gas() vehicle.turnLeft() vehicle.brake() c = Car() d = Driver() d.drive(c)
Which produces the same output as above.
Let's add a new class to the Python code:
class Pencil: def gas(self): print "Scribble scribble" def turnLeft(self): print "Left pencil turn?" # note that turnRight is missing! def brake(self): print "PUT YOUR PENCILS DOWN"
Although Pencil
having these methods makes absolutely no sense, we could pass this to the drive()
method and there will be no errors. Yep, even though Pencil
doesn't implement turnRight()
, because turnRight()
is never called, all this code will run, error free!
We have a Pencil
that can gas()
, turnLeft()
, and brake()
, just like a Car
. What is the difference between them, as far as this code is concerned? None!
This is what duck typing is. If a class acts like another class, it can substitute for that class. There's no need for there to be strictly defined relationships between classes.