posted on 09/21/08 at 09:19:28 pm by Joel Ross
I recently had a discussion with someone about duck typing, and my understanding of it was called into question. He's much smarter than I am, so I assumed he was right, but afterwards, I decided to do a little digging. I think I was right, but there's not a ton of information out there, so I'm going to lay out what I think Duck Typing is, and let you poke holes in it, and tell me where I'm wrong.
First, though, let's lay out the definition of Duck Typing. From the Wikipedia article:
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, as James Whitcomb Riley put it:
If it walks like a duck and quacks like a duck, I would call it a duck.
So what does that mean? From my understanding, it meant that as long as I pass something into a method and it supports the interface the method expects, than it'll work. For example, let's say I have the following method:
1: public void SendEmail(SmtpMailer mailer, string subject, string body)
3: mailer.SendMessage(subject, body);
This method relies on a concrete class - SmtpMailer. But what if I wanted to pass in a different class to this method? Well, the normal way to do this would be to create an interface, have SmtpMailer implement that interface, and change this method to work against an interface rather than a concrete implementation. But there's two potential downfalls of that approach. First, what if you don't have access to change the SmtpMailer class? You can't just add an interface to it, so the solution is the same, except you'd have to create an implementation of IMailer that adapts the SmtpMailer class to IMailer (a good design decision anyway). But what if this method isn't accessible for change? Then what? You could inherit from SmtpMailer and override the SendMail method, and pass in that class instead. And if both are inaccessible to you? Well, then you've got a lot of work to do to break this code apart.
All of that requires a lot of code to work around the issue. But with (my understanding of) duck typing, it's simple and requires no code changes to SendMail or the SmtpMailer class. All I have to do is have a class that satisfies the requirements of the SendEmail method. In other words, I can pass any class into this method, as long as it has a method called SendMessage that takes two strings as parameters. So, this would work:
1: public class InstantMessage
3: public void SendMessage(string subject, string body)
5: // Send subject and body via Instant Message
Now, my background is almost completely in statically typed languages, so to me, this is a pretty big paradigm shift. Maybe for those who are used to working in a dynamic language (like Ruby) on a regular basis, it's not that big of a deal. To me, it seems like a good way to deal with those tough-to-break dependencies.
1: var x = new Array();
3: x = "One";
4: x = "two";
5: x = "three";
1: x = x.join("");
In this case, x (the same variable) acts like a string after the join call, so length will return 11 (the length of the joined string).
If the latter is actually duck typing, than there's no difference between duck typing and dynamic typing. But I don't think that's the case. What I've found seems to support what I'm saying, but I've also seen conflicting definitions. So I'm turning to people smarter than me to tell me what duck typing really is - you!