From: Dan Doel Date: 2003-08-09T06:10:44+09:00 Subject: Re: Ducktype, right? Someone suggested that the discussion of what duck typing is is getting away from how it was originally used. Perhaps I'm confused, or I'm not explaining what I think in the correct way, so I'll try again. Maybe a better way of phrasing the concepts of duck typing is contract typing. If you look at Java, interfaces more-or-less define contracts between objects. If you have an interface Appendable, that's a contract that says an object will a) Have a method append() b) Implement that in a certain way a) can be had in Ruby via respond_to?, the use of which isn't required for duck typing. b) can be had more explicitly by using modules. However, modules, in my mind, are more for reusing code between class hierarchies without requiring multiple inheritance, rather than for defining what methods an object implements (although they could be used for the latter). If you really want to talk about duck typing, you'd be talking about an example along the lines of: def add_elements(foo) foo << "a" foo << "b" end This method accepts an array (foo) and adds two elements to it using the append operator. However, looked at more abstractly, this method takes any object for which << implies append in an array sense. We could actually pass in a binary search tree where << adds an element to the three, and it would work in a similar way. If we pass in a Fixnum where << is bitwise shift, then we've broken the contract. In Java, you need interfaces for this. You could write: void addElements(Array foo) { foo.append("a"); foo.append("b"); } void addElements(BST foo) { foo.append("a"); foo.append("b"); } But it's easier to have both implement Appendable, and have addElements work on anything that is Appendable. Java needs interfaces because of static type checking. In ruby you can just assume that an object implements things correctly and use it as such, which, I think, is the idea of duck typing. If you want to make it more general, you can add a respond_to? :<< and respond_to? :append, since different objects might implement either or both of those. However, the key idea is that in ruby, the contracts are dynamic. Using Java interfaces, to some degree, forces you to follow the contracts more explicitly, since you have to knowingly say you implement a contract and continue to break that contract. However, assuming that the contract is documented somewhere in the code, and everybody follows that contract, then there is no need to explicitly define modules or classes just to define the contract in code, rather than leaving it in documentation. If you do define modules for each semantic, then you end up with each of your classes including 10 different modules just so that code can check and see if a class follows some contract (look through the Java standard library and you'll see many classes like this). You're effectively turning ruby into a statically typed language where all the type checking is done by you at runtime. So another way of saying "duck typing" is "programming with implicit contracts" or "implicit contract typing" or something like that, rather than Java, where implicit is replaced with explicit. This is really something of a feature of any language that isn't statically typed. The difference in the case of ruby is that, although you can check the class of an object with is_a? (or something like that), there's no way to tell from the class itself whether it will satisfy the contract. You have to assume it does. So having respond_to? :quack doesn't make it a duck. It's also how quack is implemented, and there's no way to really check that without testing. Duck typing means making assumptions. Anyhow, that's my take on it all, at the end of the day. I hope I'm not too off base. If I am, then Dave can yell at me. - Dan