What is duck typing?
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.
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.
Prologue
I tried to keep it simple/fun by cutting out pedantic nuances and academic-speak. This approach is not for everyone - if you prefer an academic definition check out the wikipedia article to duck typing, or Matt Damon's explanation to duck typing in Good Will Hunting ;)
Code Sample
But how can a golf club "drive" like a car? Aren't they different? Not so, if you're using a language like Ruby:
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
end
car = Car.new
test_drive(car) #=> "I'm driving a Car"
club = GolfClub.new
test_drive(club) #=> "I"m driving a GolfClub"
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:
精彩评论