I came across the term duck typing while reading random topics on software online and did not completely understand it.

What is “duck typing”?


Solution 1:

It is a term used in dynamic languages that do not have strong typing.

The idea is that you don't need a type in order to invoke an existing method on an object - if a method is defined on it, you can invoke it.

The name comes from the phrase "If it looks like a duck and quacks like a duck, it's a duck".

Wikipedia has much more information.

Solution 2:

Duck typing means that an operation does not formally specify the requirements that its operands have to meet, but just tries it out with what is given.

Unlike what others have said, this does not necessarily relate to dynamic languages or inheritance issues.

Example task: Call some method Quack on an object.

Without using duck-typing, a function f doing this task has to specify in advance that its argument has to support some method Quack. A common way is the use of interfaces

interface IQuack { 
    void Quack();
}

void f(IQuack x) { 
    x.Quack(); 
}

Calling f(42) fails, but f(donald) works as long as donald is an instance of a IQuack-subtype.

Another approach is structural typing - but again, the method Quack() is formally specified anything that cannot prove it quacks in advance will cause a compiler failure.

def f(x : { def Quack() : Unit }) = x.Quack() 

We could even write

f :: Quackable a => a -> IO ()
f = quack

in Haskell, where the Quackable typeclass ensures the existence of our method.


So how does **duck typing** change this?

Well, as I said, a duck typing system does not specify requirements but just tries if anything works.

Thus, a dynamic type system as Python's always uses duck typing:

def f(x):
    x.Quack()

If f gets an x supporting a Quack(), everything is fine, if not, it will crash at runtime.

But duck typing doesn't imply dynamic typing at all - in fact, there is a very popular but completely static duck typing approach that doesn't give any requirements too:

template <typename T>
void f(T x) { x.Quack(); } 

The function doesn't tell in any way that it wants some x that can Quack, so instead it just tries at compile time and if everything works, it's fine.