So, What is Duck Typing?

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)
   2:  {
   3:    mailer.SendMessage(subject, body);
   4:  }

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
   2:  {
   3:    public void SendMessage(string subject, string body)
   4:    {
   5:      // Send subject and body via Instant Message
   6:    }
   7:  }

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.

Now, when I described the above as Duck Typing, I was told that wasn't actually what duck typing was. Here's how it was described to me. Essentially, a variable can change types based on the way it's assigned - like what JavaScript provides. You can declare a variable and use it like so:

   1:  var x = new Array();
   2:   
   3:  x[0] = "One";
   4:  x[1] = "two";
   5:  x[2] = "three";
   6:   
   7:  alert(x.length);

Calling length on x returns 3 - the length of the array. Because x is being used as an array, that's how the method responds. But since Javascript is dynamically typed, I can later repurpose x:

   1:  x = x.join("");
   2:  alert(x.length);

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!

Tags: | |

Categories: Development

24 comments »


 

24 comments

Comment from: Steven Harman [Visitor] Email · http://stevenharman.net
Joel, You're understand of duck typing is correct - as long as your object satisfies the requirements (i.e.:supports the methods) of whomever is using it, then who cares what type the object is.

Hence, if it walks like a duck and quacks like a duck, as far as I care, its a duck!

I don't know what "the other guy" what thinking when he gave you that other definition... but that's more along the lines of dynamic/implicit typing - so you were correct to challenge that definition.
09/21/08 @ 22:14
Comment from: Joel Ross [Member] Email · http://www.rosscode.com
Steven,

Thanks for the feedback. I've heard people use duck typing and dynamic typing interchangeably in the past as well, so I don't really fault him, and it was just a part of a larger conversation. It just happened to stick with me, so I had to clarify it.
09/21/08 @ 23:44
Comment from: Jay R. Wren [Visitor] Email · http://jrwren.wrenfam.com/blog/
everything you need to know about duck typing in a .net static language:

http://boo.codehaus.org/Duck+Typing

:)
09/22/08 @ 13:11
Comment from: Mike Moore [Visitor] Email · http://blowmage.com/
Far be if from me to disagree with the mighty Wikipedia, but Duck Typing is not a typing system like static vs. dynamic or string vs. weak. It is not a "style _of_ dynamic typing", it is a style of programming using dynamic languages. Duck typing is simply preferring composition over inheritance.

While your example using interfaces is a way to demonstrate duck typing, it really is flawed. Languages that use compile time type checking are inherently incapable of duck typing. There is just way too much reliance on inheritance. Your implementation of the interface is checked by looking at the type of you object passed in at compile time. So even interfaces prefer inheritance over composition.

Your JavaScript example isn't really great either. The example I've liked came from Dave Thomas using Ruby. He had an app that would build the contents of a CSV file into a string. But the app would use too much memory with alot of data (due to inefficient string concatenation), so he instead passed in an array. Because all the methods were already appending to the string with the '<< method, and the array also has an '<<' method, his code worked unchanged (except for converting the array to a string at the end).

You can check your objects and ensure that they are an implementation or child of a particular class when using a dynamic (and strongly) typed language; it is possible to prefer inheritance over composition in dynamic languages. But duck typing prefers composition over inheritance and is really only possible in a dynamic languages.
09/22/08 @ 22:20
Comment from: Zach Moazeni [Visitor] Email · http://simplechatter.com
A preface:
I'm speaking closer towards Java's statically typed language, but I feel my argument follows with most mainstream statically typed languages. Some common language: 'interface' = A known outside behavior of an object, mainly public methods. 'Interface' = a language defined type to enforce the implementation to define all interface methods.

Mike,

While I agree that some of his examples have flaws, I disagree largely on the argument that duck typing "is simply preferring composition over inheritance." I would say duck typing is about not requiring implementation knowledge of the Interface (notice caps) or Class passed in at compile time. Duck Typing is more about expecting and using an interface at runtime without knowing either the real implementation or the Interface (not caring the compiled type).

Now where I disagree with the relationship between Duck Typing and favoring composition over inheritance. You can write composed code using Interfaces. The idea behind a use of Java's Interfaces is to abstract the interface from the implementation. You don't necessarily know the explicit implementation that was passed in, nor do you have to assume that it gained it's functionality via inheritance. There is quite a bit of literature about writing small, non-inherited, composed classes, and consuming them as Interfaces, which decouples the implementation from the real interface. In essence, it allows you to swap out implementations, without changing the consuming code.

Regardless of my disagreement with the relationship Mike's mentioning, I really enjoy developing code in languages that employ Duck Typing. I've found when used in conjunction with automated tests, I experience a much greater net benefit in productivity and readability.
09/22/08 @ 22:54
Comment from: Zach Moazeni [Visitor] Email · http://simplechatter.com
Wow, even after a few proofreads, evil grammatical errors slipped in. I shouldn't be posting blog comments after 11:00.

Hope you guys can still make out my message through the obfuscation.
09/22/08 @ 23:03
Comment from: Joel Ross [Member] Email · http://www.rosscode.com
Mike,

Thanks for the comment. All of my experience comes from a statically typed programming background, so you'll have to forgive my forcing the round (dynamic) peg in the square (static) hole.

I'm still not sure I see the connection between duck typing and composition, but I'll keep digging.
09/22/08 @ 23:17
Comment from: Joel Ross [Member] Email · http://www.rosscode.com
Zach,

Java developer?!? You sure you're in the right place? ;-) Seriously though. Thanks for the comment.
09/22/08 @ 23:21
Comment from: Mike Moore [Visitor] Email · http://blowmage.com/

Hi Zach, I see what you are saying. However, with the modern Alt.NET approach you typically abstract your application code away from the BCL. So even though this was not in Joel's original post, I was assuming the existence of some Interface like IMessageSender. Maybe something like this: (I hope the formatting turns out.)



public interface IMessageSender {

  public void SendMessage(string subject, string body);

}



And then your email class would be:



public class MailMessage : IMessageSender {

  public void SendMessage(string subject, string body) {

    // Send message via SmtpMailer

  }

}



And your instant message class would be:



public class InstantMessage : IMessageSender {

  public void SendMessage(string subject, string body) {

    // Send message via some Jabber lib

  }

}



In these cases you could approximate "duck typing". And there is really no other way to duck type in C#, because of the static type checking at compile time. C# and Java have to know that the class implements the interface however; they have to know something about the implementation. There is no way to use the object because of it's composition and not it's inheritance (or implementation). Therefor, duck typing is simply preferring composition over inheritance in a dynamic language. The laissez faire attitude towards typing is important.

09/22/08 @ 23:37
Comment from: Joel Ross [Member] Email · http://www.rosscode.com
Mike,

The formatting turned out great. And I understand what you're saying now about composition over inheritance. I thought you were speaking to the classical definition of composition - using sub objects to perform actions instead of inheriting from a class. Instead, you're talking about the physical make up of the class. Thanks for the clarification.

In fact, in my sample, I was specifically saying that there wasn't an IMessageSender. In fact, what I wrote doesn't work in C#. I just used C# syntax because that's what I know (and assume my readers are familiar with).

In fact, the conversation was around a feature I'd like to see in C# that isn't there now, which is where some of the original confusion came from.
09/22/08 @ 23:50
Comment from: Mike Moore [Visitor] Email · http://blowmage.com/
Joel, I understood that the code in your article wouldn't work, and I wasn't as clear about my assumptions in my first comment of using an Interface to get the code to work as I'd hoped. Glad the clarification helped.
09/22/08 @ 23:57
Comment from: Zach Moazeni [Visitor] Email · http://simplechatter.com
(This is getting the size of a blog post in itself, Ross if you feel this is hijacking your blog post, you can delete this comment, and I'll post the response on my blog).

So I'll definitely have to profess ignorance of C# and .NET. Most of my statically typed experience was in Java before I left for Ruby years ago. While your example shows inheritance at the interface level, I still maintain that Duck Typing and Favoring Composition over Inheritance (going to use CvI from here on out) are separate conversations.

First, Duck Typing mostly applies to the consumer code: the code that calls some implementation (regardless if it's real type is known at compile time). CvI mostly applies to the consumed code: the code that gets called. CvI is about a practice of writing code to push behavior into smaller objects that collaborate with other (preferably small) objects.

Secondly, you can easily write code non-CvI code in Dynamically Typed languages that employ Duck Typing (intentionally not saying Duck Typed languages because to my knowledge, that doesn't make sense). Here's an example in Ruby with some annotations for non-Ruby coders:


# Example of non-CvI code

class Shape
... some other code about length and height ..

def get_area # this is how you define of a function
# re-implement in subclasses
self.length * self.height
end
end

class Rectangle < Shape
# don't need to implement get_area because we're good with the superclass's definition
end

class Triangle < Shape # this means Triangle inherits from Shape
def get_area # we reimplement the method since we can't share the parent's functionality
1/2 * self.length * self.height
end
end

# Example of CvI code

class Shape
# no definition of area
end

class Triangle < Shape
def initialize # this is the constructor
@area_calculator = ThreeEdgeDimensionator.new(self) # we're assigning an instance variable and instantiating an new class
end

def get_area
@area_calculator.get_area # Here we depend upon the other object in order to calculate the area
end
end

class Rectangle < Shape
def initialize
@area_calculator = TwoEdgeDimensionator.new(self)
end

def get_area
@area_calculator.get_area
end
end

class Square < Shape
def initialize
@area_calculator = TwoEdgeDimensionator.new(self) # This class is used between both Rectangle and Square to share functionality
end

def get_area
@area_calculator.get_area
end
end


(I do hope the Ruby syntax doesn't detract from the overall message.)

Now obviously this is contrived example, but you can see the basic difference between the two structures. The first relies on hopefully-inherited implementation to calculate the area. However the second relies on a shared class that can be reused among implementations that desire the behavior. Both examples are consumed the exact same way (duck typed since Ruby doesn't declare the types in the consumer's code):


def area_of_shape(some_shape) # We don't have to define the class or interface of the variable "some_shape"
return some_shape.get_area() # At runtime, the virtual machine (if the code runs on one) determines if "some_shape" can accept the method "get_area()"
end


Now while this is contrived, as new people learn Object Oriented programming, one of the initial tenets is "OO is supposed help share functionality through inheritance." However in sufficiently large-scoped projects, sharing behavior via inheritance becomes more of a maintenance burden than a helpful, scalable tool to rely on. Furthermore, there are tons of projects/libraries out there across many OO languages that expect the developers extending the code to inherit existing classes in order to extend functionality. UI Toolkits such as Java's Swing is a great example of this bad concept.

Regarding your C# examples:


public interface MailMessage : IMessageSender {
public void SendMessage(string subject, string body) {
// Send message via SmtpMailer
}
}


This really doesn't make sense to me, and we may be talking past each other because of my ignorance of C#. The fact that MailMessage has an actual implementation for "SendMessage" AND it is still called an "interface" is surprising. However, it may just be a typo because you refer to both MailMessage and InstantMessage as classes.


In these cases you could approximate "duck typing". And there is really no other way to duck type in C#, because of the static type checking at compile time. C# and Java have to know that the class implements the interface however; they have to know something about the implementation.


I'm not arguing that this mimics Duck Typing in a statically typed language.


There is no way to use the object because of it's composition and not it's inheritance (or implementation). Therefor, duck typing is simply preferring composition over inheritance in a dynamic language.


I actually don't see an example of composition in either of those class examples. You may be applying the phrase "favor composition over inheritance" in a different meaning than the generally argued concept. In which case we may be talking past each other in that regard as well. CvI is mainly the argument that sharing functionality through inheritance is a bad idea, and that a developer should prefer composition (or aggregation) (or collaboration) with other objects in order to share functionality.

Finally, CvI leads to other concepts that follow OO Design ideas. Examples being: Dependency Injection and Mock Testing. These concepts are applied across many languages that may or may not employ Duck Typing. So in the end I see little-to-no relationship between Duck Typing and CvI.

Here's a few other resources that may articulate the point better than I:
* http://www.atomicobject.com/pages/Inheritance
* http://www.artima.com/designtechniques/compoinh.html
* http://oreilly.com/catalog/9780596007126/ - A great book that outlines Design Patterns, and I believes has a section devoted to the concept CvI
09/23/08 @ 00:51
Comment from: Zach Moazeni [Visitor] Email · http://simplechatter.com
Gah, the code snipbits didn't turn out well. Here's all the code with syntax highlighting and better indentation: http://www.pastebin.cz/9339
09/23/08 @ 00:58
Comment from: Mike Moore [Visitor] Email · http://blowmage.com/
Oops, both MailMessage and InstantMessage should have been classes. Stupid copy/paste mistake due to trying to keep the formatting.
09/23/08 @ 01:06
Comment from: Andrew Clay Shafer [Visitor] Email · http://stochasticresonance.wordpress.com
I have to agree with Zach that Duck Typing and CvI are orthogonal.

The original quote from the Gang of Four Design Principles is "Favor object composition over class inheritance." CvI is usually used to advocate behavior be added through delegation to objects that provide it, typically as instance variables, rather than inheriting from those same objects.

In all previous discussions I've seen or had on this topic, that means to favor 'has a' vs 'is a'.

By definition Duck Typing is another form of 'is a', but 'is a' determined by behavior rather than a strict definition of type.

That boo project has an interesting approach to fake Duck Typing in a static type system. Although there are also statically typed languages that do support DT http://enfranchisedmind.com/blog/2008/04/14/useful-things-about-static-typing/

To me Duck Typing is very similar to what Interfaces enable in Java and C# except DT is an implicit contract rather than the explicit contract the compiler will enforce.

This means I can pass any object into a method, as long as it can accept the messages that will get sent to it, and further that implicit contract also cascades to any of the objects returned. While there are no compile time checks, the runtime will quickly let me know when a method is not implemented.

I have a personal theory that this is one of the reasons the testing culture is so strong in Ruby relative to many other languages. Between Duck Typing, method missing meta programming and open classes, if a program isn't brought under test, you almost have no hope of knowing what the hell will happen when you run it... :/
09/23/08 @ 03:39
Comment from: Joel Ross [Member] Email · http://www.rosscode.com
Mike,

I edited your comment, changing the two implementations to be classes.
09/23/08 @ 08:03
Comment from: Joel Ross [Member] Email · http://www.rosscode.com
Zach and Andrew,

I think what Mike was saying finally clicked with me last night. I don't think he is actually talking about composition in terms of delegation. He's referring to composition in terms of the object's current make up, rather than it's hierarchical structure.
09/23/08 @ 08:54
Comment from: Mike Moore [Visitor] Email · http://blowmage.com/
Yeah, what Joel said. And even though all you pattern weenies are correct in the context of the GoF, the net result is the same: the object you are left with has no inhertitance heirarchy for you statically check at compile time. When the consuming code has the ability to not care what type an object is and only cares if it responds to the right methods, then you can duck type.

Also, I would argue that this process needs to be done at runtime, otherwise you just have compier tricks estimating duck typing.

(All this for a term that is long in the tooth and, like "Monkey Patching", probably needs to be retired...)
09/23/08 @ 09:33
Comment from: Andrew Clay Shafer [Visitor] Email · http://stochasticresonance.wordpress.com
Semantics matter, which is why this thread started in the first place.

Composition has a meaning in the context of object systems and another in the context of functional systems.

Surely introducing a third meaning, particularly in a context (object systems) where it already has a definition, is going to lead to some ambiguity.

If I understand correctly, you are using 'composition' similarly to the definition provided earlier for 'interface' (little 'i', as opposed to 'Interface' as a language feature). Can anyone direct me to another resource or discussion where 'composition' is being used this way?
09/23/08 @ 13:53
Comment from: Greg M [Visitor] Email
Duck typing in a statically-typed language:


interface Duckable{
void* duck(String methodname, void[] args
}


now implement Duckable _everywhere_ with a default of:

duck(s,a) {
throw "Method missing"
}


But of course you wouldn't choose to do this; it's better to enforce it statically by creating an interface specifically for your purpose.
09/24/08 @ 03:59
Comment from: Joel Ross [Member] Email · http://www.rosscode.com
Greg,

If you control all aspects of the software, then duck typing might not be as useful to you, since the safer way to do it would be with fine-grained interfaces that are checked at compile time.

But the reality in a lot of cases is that you don't have that ability. Think about the CLR. How many times have you wanted to do something different with a class, but you didn't have a way to do it because it's sealed or doesn't have an interface that you can use? If you had duck typing, you could still do it.

Note that I'm not saying this is valid in C# or a statically typed language - I just happened to use C# syntax to communicate my point.
09/24/08 @ 09:24
Comment from: Greg M [Visitor] Email
Mmm yeah, but that's a limitation of the specific language you're talking about, not of statically typed languages in general. As long as you can declare that a type meets an interface independent of that type's initial declaration (you can do this in Haskell for instance) then you don't have this problem. C#'s extension methods nearly get you there, it's just lacking an analogous extension-"implements" feature.
09/25/08 @ 02:15
Comment from: Joel Ross [Member] Email · http://www.rosscode.com
Greg,

I didn't realize that there are statically typed languages where you can add interface implementations independent of it's declaration. That's pretty cool.

I'm guessing you're talking about true Interfaces (capital I, from Zach's earlier comment). What I was referring to is the times where there is no Interface to deal with - it's a class that isn't open, so you can't work around those limitations. That's where I can see Duck Typing being useful.
09/25/08 @ 08:12
Comment from: Paddy3118 [Visitor] Email · http://paddy3118.blogspot.com
If you don't have run-time checking then you don't have have Duck typing. The Boo language and I think C# version 4.0 have implemented Duck typing by adding syntax that says "Check this at Runtime not compile time", in order to support Duck Typing.

More info on what is/is not Duck Typing but is given in the Wikipedia article, and there is also useful information in amongst the talk page entries including http://en.wikipedia.org/wiki/Talk:Duck_typing#Confusing_template_sentence-.3E.28no.29_Static_vs_Dynamic_typing

- Paddy.
11/05/08 @ 11:49

Leave a comment


Your email address will not be revealed on this site.

Your URL will be displayed.
(Line breaks become <br />)
(Name, email & website)
(Allow users to contact you through a message form (your email will not be revealed.)