What does duck typing mean in software development?
It is a term used in dynamic languages that do not have strong typing.
The idea is that you don't need to specify 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.
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 quack
s 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.
def f(x)
instead of def f(IQuack x)
. –
Dioecious Simple Explanation
What is duck typing?
“If it walks like a duck and quacks like a.... etc” - YES, but what does that mean??!
We're interested in what "objects" can do, rather than what they are.
Let's unpack it with an example:
See below for further detail:
Examples of Duck Typing functionality:
Imagine I have a magic wand. It has special powers. If I wave the wand and say "Drive!" to a car, well then, it drives!
Does it work on other things? Not sure: so I try it on a truck. Wow - it drives too! I then try it on planes, trains and 1 Woods (they are a type of golf club which people use to 'drive' a golf ball). They all drive!
But would it work on say, a teacup? Error: KAAAA-BOOOOOOM! that didn't work out so good. ====> Teacups can't drive!! duh!?
This is basically the concept of duck typing. It's a try-before-you-buy system. If it works, all is well. But if it fails, like a grenade still in your hand, it's gonna blow up in your face.
In other words, we are interested in what the object can do, rather than with what the object is.
What about languages like C# or Java etc?
If we were concerned with what the object actually was, then our magic trick will work only on pre-set, authorised types - in this case cars, but will fail on other objects which can drive: trucks, mopeds, tuk-tuks etc. It won't work on trucks because our magic wand is expecting it to only work on cars.
In other words, in this scenario, the magic wand looks very closely at what the object is (is it a car?) rather than what the object can do (e.g. whether cars, trucks etc. can drive).
The only way you can get a truck to drive is if you can somehow get the magic wand to expect both trucks and cars (perhaps by "implementing a common interface"). This can be done via a technique called: "polymorphism" or by using "interfaces" - they're kinda the same thing. If you like cartoons and want an explanation, check out my cartoon on interfaces.
Summary: Key take-out
What's important in duck typing is what the object can actually do, rather than what the object is.
Code Sample
But how can a golf club "drive" like a car? Aren't they different? If you're using a language like Ruby, we don't care about what the object is:
class Car
def drive
"I"m driving a Car!"
end
end
class GolfClub
def drive
"I"m driving a golf club!"
end
end
def test_drive(item)
item.drive # don't care what it is, all i care is that it can "drive"
end
car = Car.new
test_drive(car) #=> "I'm driving a Car"
club = GolfClub.new
test_drive(club) #=> "I"m driving a GolfClub"
# welcome to duck typing!
PS. I wanted to cut out the academic rigmarole: this answer is not scientific, but hopefully it gives you a vague understanding of what is going on via analogy.
PPS. if you wanna laugh and got some time to spare, check out: Matt Damon's explanation of duck typing in Good Will Hunting ;)
Consider you are designing a simple function which gets an object of type Bird
and calls its walk()
method. There are two approaches you can think of:
- This is my function, and I must be sure that it only accepts the
Bird
type or the code will not compile. If anyone wants to use my function, they must be aware that I only acceptBird
s. - My function gets any
objects
and I just call the object'swalk()
method. So, if theobject
canwalk()
then it is correct. If it can't, my function will fail. So, here it is not important the object is aBird
or anything else, it is important that it canwalk()
(This is duck typing).
It must be considered that duck typing may be useful in some cases. For example, Python uses duck typing a lot.
Useful reading
- There are good examples of duck typing for Java, Python, JavaScript etc. at https://en.wikipedia.org/wiki/Duck_typing.
- Here is also a good answer which describes the advantages of dynamic typing and also its disadvantages: What is the supposed productivity gain of dynamic typing?
I see a lot of answers that repeat the old idiom:
If it looks like a duck and quacks like a duck, it's a duck
and then dive into an explanation of what you can do with duck typing, or an example which seems to obfuscate the concept further.
I don't find that much help.
This is the best attempt at a plain english answer about duck typing that I have found:
Duck Typing means that an object is defined by what it can do, not by what it is.
This means that we are less concerned with the class/type of an object and more concerned with what methods can be called on it and what operations can be performed on it. We don't care about it's type, we care about what it can do.
Don't be a quack; I've got your back:
"Duck typing" := "try the methods, don't check the type"
Note: :=
can be read as "is defined as".
"Duck typing" means: just try the method (function call) on whatever object comes in rather than checking the object's type first to see if that method is even a valid call on such a type.
Let's call this "try the methods, don't check the type" typing, "method-call type-checking", or just "method-call typing" for short.
In the longer explanation below, I'll explain this more in detail and help you make sense of the ridiculous, esoteric, and obfuscated term "duck typing."
Longer explanation:
DIE 🦆 DIE! 🍗
Python does this concept above. Consider this example function:
def func(a):
a.method1()
a.method2()
When the object (input parameter a
) comes into the function func()
, the function shall try (at run time) to call any methods specified on this object (namely: method1()
and method2()
in the example above), rather than first checking to see if a
is some "valid type" which has these methods.
So, it's an action-based attempt at run-time, NOT a type-based check at compile-time or run-time.
Now look at this silly example:
def func(duck_or_duck_like_object):
duck_or_duck_like_object.quack()
duck_or_duck_like_object.walk()
duck_or_duck_like_object.fly()
duck_or_duck_like_object.swim()
Hence is born the ridiculous phrase:
If it walks like a duck and quacks like a duck then it is a duck.
The program that uses "duck typing" shall simply try whatever methods are called on the object (in this example above: quack()
, walk()
, fly()
, and swim()
) withOUT even knowing the type of the object! It just tries the methods! If they work, great, for all the "duck typing" language knows or cares, IT (the object passed in to the function) IS A DUCK!--because all the (duck-like) methods worked on it.
(Summarizing my own words):
A "duck typed" language shall not check its type (neither at compile time nor run-time)--it doesn't care to. It will just try the methods at run-time. If they work, great. If they don't, then it shall throw a run-time error.
That is duck-typing.
I'm so tired of this ridiculous "duck" explanation (because without this full explanation it doesn't make any sense at all!), and so are others too it sounds like. Example: from BKSpurgeon's answer here (my emphasis in bold):
(“If it walks like a duck and quacks like a duck then it is a duck.”) - YES! but what does that mean??!"
Now I get it: just try the method on whatever object comes in rather than checking the object's type first.
I shall call this "run-time checking where the program just tries the methods called without even knowing if the object has these methods, rather than checking the type of the object first as the means of knowing the object has these methods", because that just makes more sense. But...that's too long to say, so people would rather confuse each other for years instead by saying ridiculous but catchy things like "duck typing."
Let's instead call this: "try the methods, don't check the type" typing. Or, perhaps: "method-call type-checking" ("method-call typing" for short), or "indirect type-checking by method calls", since it uses the calling of a given method as "proof enough" that the object is of the right type, rather than checking the object's type directly.
Note that this "method-call type-checking" (otherwise confusingly called "duck typing") is a type of dynamic typing. But, NOT all dynamic typing is necessarily "method call type-checking", because dynamic typing, or type checking at run-time, can also be done by actually checking an object's type rather than by simply attempting to call the methods called on the object in the function without knowing its type.
Read also:
- https://en.wikipedia.org/wiki/Duck_typing --> search the page for "run", "run time", and "runtime".
Wikipedia has a fairly detailed explanation:
http://en.wikipedia.org/wiki/Duck_typing
duck typing is a style of dynamic typing in which an object's current set of methods and properties determines the valid semantics, rather than its inheritance from a particular class or implementation of a specific interface.
The important note is likely that with duck typing a developer is concerned more with the parts of the object that are consumed rather than what the actual underlying type is.
I know I am not giving generalized answer. In Ruby, we don’t declare the types of variables or methods— everything is just some kind of object. So Rule is "Classes Aren’t Types"
In Ruby, the class is never (OK, almost never) the type. Instead, the type of an object is defined more 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.
For example, you may be writing a routine to add song information to a string. If you come from a C# or Java background, you may be tempted to write this:
def append_song(result, song)
# test we're given the right parameters
unless result.kind_of?(String)
fail TypeError.new("String expected") end
unless song.kind_of?(Song)
fail TypeError.new("Song expected")
end
result << song.title << " (" << song.artist << ")" end
result = ""
append_song(result, song) # => "I Got Rhythm (Gene Kelly)"
Embrace Ruby’s duck typing, and you’d write something far simpler:
def append_song(result, song)
result << song.title << " (" << song.artist << ")"
end
result = ""
append_song(result, song) # => "I Got Rhythm (Gene Kelly)"
You don’t need to check the type of the arguments. If they support << (in the case of result) or title and artist (in the case of song), everything will just work. If they don’t, your method will throw an exception anyway (just as it would have done if you’d checked the types). But without the check, your method is suddenly a lot more flexible. You could pass it an array, a string, a file, or any other object that appends using <<, and it would just work.
Looking at the language itself may help; it often helps me (I'm not a native English speaker).
In duck typing
:
1) the word typing
does not mean typing on a keyboard (as was the persistent image in my mind), it means determining "what type of a thing is that thing?"
2) the word duck
expresses how is that determining done; it's kind of a 'loose' determining, as in: "if it walks like a duck ... then it's a duck". It's 'loose' because the thing may be a duck or may not, but whether it actually is a duck doesn't matter; what matters is that I can do with it what I can do with ducks and expect behaviors exhibited by ducks. I can feed it bread crumbs and the thing may go towards me or charge at me or back off ... but it will not devour me like a grizzly would.
Matt Damon explains Duck Typing in Good Will Hunting
Transcript is as below. Video link here..
CHUCKIE: All right, are we gonna have a problem?
CLARK: There's no problem. I was just hoping you could give me some insight into what duck typing is actually is? My contention is that duck tying is not well defined, and neither is strong
WILL: [interrupting] …and neither is strong typing. Of course that's your contention. You're a first year grad student: you just got finished reading some article on duck typing, probably on StackOverflow, and you’re gonna be convinced of that until next month when you get to the Gang of Four, and then you’re gonna be talking about how Google Go and Ocaml are statistically typed languages with structural sub-tying construction. That's going to last until next year, till you're probably gonna be in here regurgitating Matz, talkin’ about, you know, the Pre-Ruby 3.0 utopia and the memory allocating effects of sub-typing on the GC.
CLARK: [taken aback] Well as a matter of fact I won't, because Matz drastically underestimates the impact of —
WILL: "Matz dramatically underestimates the impact of Ruby 3.0's GC on performance. You got that from Donald Knuth, The Art of Computer Programming, page 98, right? Yeah I read that too. Were you gonna plagiarize the whole thing for us—you have any thoughts of—of your own on this matter? Or do—is that your thing, you come into stack overflow, you read some obscure passage on r/ruby and then you pretend, you pawn it off as your own—your own idea just to impress some girls, embarrass my friend?
[Clark is stunned]
WILL: See the sad thing about a guy like you is in about 50 years you’re gonna start doing some thinking on your own and you’re gonna come up with the fact that there are three certainties in life. One, don't do that. And two, if it walks like a duck then it is a duck. And three, you dropped a hundred and fifty grand on an education you coulda got for zero cents via a stack overflow answer by Ben Koshy.
CLARK: Yeah, but I will have a degree, and you'll be serving my kids some cheap html via react at a drive-thru on our way to a skiing trip.
WILL: [smiles] Yeah, maybe. But at least I won't be unoriginal.
(a beat)
WILL: you got problem 3 ? I guess we can step outside and sort things out.
Clark: there's no problem
Some time later:
WILL: Do you like apples?
Clark is like, huh?
WILL: How do you like them apples? (Boom: Will slams a letter up against a window.) I gotta offer from Google! (Shows the letter of acceptance to Clark showing his interview answer: a picture of a duck walking, and talking, and acting like a... goose.)
THE END.
(This is a footnote to the old answer here:)
3 Advent of Code problems.
Duck typing:
If it talks and walks like a duck, then it is a duck
This is typically called abduction (abductive reasoning or also called retroduction, a clearer definition I think):
from C (conclusion, what we see) and R (rule, what we know), we accept/decide/assume P (Premise, property) in other words a given fact
... the very basis of medical diagnosis
with ducks: C = walks, talks, R = like a duck, P = it's a duck
Back to programming:
object o has method/property mp1 and interface/type T requires/defines mp1
object o has method/property mp2 and interface/type T requires/defines mp2
...
So, more than simply accepting mp1... on any object as long has it meets some definition of mp1..., compiler/runtime should also be okay with the assertion o is of type T
And well, is it the case with examples above? Is Duck typing is essentially no typing at all? Or should we call it implicit typing?
Duck Typing is not Type Hinting!
Basically in order to use "duck typing" you will not target a specific type but rather a wider range of subtypes (not talking about inheritance, when I mean subtypes I mean "things" that fit within the same profiles) by using a common interface.
You can imagine a system that stores information. In order to write/read information you need some sort of storage and information.
Types of storage may be: file, database, session etc.
The interface will let you know the available options (methods) regardless of the storage type, meaning that at this point nothing is implemented! In another words the Interface doesn't know nothing about how to store information.
Every storage system must know the existence of the interface by implementing it's very same methods.
interface StorageInterface
{
public function write(string $key, array $value): bool;
public function read(string $key): array;
}
class File implements StorageInterface
{
public function read(string $key): array {
//reading from a file
}
public function write(string $key, array $value): bool {
//writing in a file implementation
}
}
class Session implements StorageInterface
{
public function read(string $key): array {
//reading from a session
}
public function write(string $key, array $value): bool {
//writing in a session implementation
}
}
class Storage implements StorageInterface
{
private $_storage = null;
function __construct(StorageInterface $storage) {
$this->_storage = $storage;
}
public function read(string $key): array {
return $this->_storage->read($key);
}
public function write(string $key, array $value): bool {
return ($this->_storage->write($key, $value)) ? true : false;
}
}
So now, every time you need to write/read information:
$file = new Storage(new File());
$file->write('filename', ['information'] );
echo $file->read('filename');
$session = new Storage(new Session());
$session->write('filename', ['information'] );
echo $session->read('filename');
In this example you end up using Duck Typing in Storage constructor:
function __construct(StorageInterface $storage) ...
Hope it helped ;)
Tree Traversal with duck typing technique
def traverse(t):
try:
t.label()
except AttributeError:
print(t, end=" ")
else:
# Now we know that t.node is defined
print('(', t.label(), end=" ")
for child in t:
traverse(child)
print(')', end=" ")
I think it's confused to mix up dynamic typing, static typing and duck typing. Duck typing is an independent concept and even static typed language like Go, could have a type checking system which implements duck typing. If a type system will check the methods of a (declared) object but not the type, it could be called a duck typing language.
The term Duck Typing is a lie.
You see the idiom “If it walks like a duck and quacks like a duck then it is a duck." that is being repeated here time after time.
But that is not what duck typing (or what we commonly refer to as duck typing) is about. All that the Duck Typing we are discussing is about, is trying to force a command on something. Seeing whether something quacks or not, regardless of what it says it is. But there is no deduction about whether the object then is a Duck or not.
For true duck typing, see type classes. Now that follows the idiom “If it walks like a duck and quacks like a duck then it is a duck.". With type classes, if a type implements all the methods that are defined by a type class, it can be considered a member of that type class (without having to inherit the type class). So, if there is a type class Duck which defines certain methods (quack and walk-like-duck), anything that implements those same methods can be considered a Duck (without needing to inherit Duck).
In duck typing, an object's suitability (to be used in a function, for example) is determined based on whether certain methods and/or properties are implemented rather than based on the type of that object.
For example, in Python, the len
function can be used with any object implementing the __len__
method. It doesn't care if that object is of a certain type say string, list, dictionary or MyAwesomeClass, as far as these objects implement a __len__
method, len
will work with them.
class MyAwesomeClass:
def __init__(self, str):
self.str = str
def __len__(self):
return len(self.str)
class MyNotSoAwesomeClass:
def __init__(self, str):
self.str = str
a = MyAwesomeClass("hey")
print(len(a)) # Prints 3
b = MyNotSoAwesomeClass("hey")
print(len(b)) # Raises a type error, object of type "MyNotSoAwesomeClass" has no len()
In other words, MyAwesomeClass
looks like a duck and quacks like a duck and therefore is a duck, while MyNotSoAwesomeClass
doesn't look like a duck and doesn't quack, therefore is not a duck!
Duck Typing:
let anAnimal
if (some condition)
anAnimal = getHorse()
else
anAnimal = getDog()
anAnimal.walk()
The above function call will not work in Structural typing
The following will work for Structural typing:
IAnimal anAnimal
if (some condition)
anAnimal = getHorse()
else
anAnimal = getDog()
anAnimal.walk()
That's all, many of us already know duck typing is intuitively.
In programming, types can be divided into nominal and structural types. Nominal types consider the entire structure of a type. So from whom inherited etc. They are clearly more complex than structural types. One uses nominal types for example in C# and Java.
Structural types do not consider these points at all. For structural types only the structure of the single type is important. So how it looks like. In the example of a class. Does it have the same parameters and the expected types. This is called Duck Typing. Duck Typing finds its origin in the Duck Test.
A Dugtest means: If something looks like a duck. If it swims like a duck. If it quacks like a duck. Then it is a duck. Conversely: If a test case does not apply, then it is not a duck. (https://en.wikipedia.org/wiki/Duck_test)
I try to understand the famous sentence in my way: "Python dose not care an object is a real duck or not. All it cares is whether the object, first 'quack', second 'like a duck'."
There is a good website. http://www.voidspace.org.uk/python/articles/duck_typing.shtml#id14
The author pointed that duck typing let you create your own classes that have their own internal data structure - but are accessed using normal Python syntax.
© 2022 - 2024 — McMap. All rights reserved.
StackExchange
community – BesomGetEnumerator()
method. You don't have to implementIEnumerable
. – Northwesterly