From: Rick DeNatale Date: 2006-08-23T00:26:55+09:00 Subject: Re: Strategy pattern / interface design arrangement On 8/22/06, William Crawford wrote: > Oliver Bandel wrote: > > A while ago I heard about duck typing. > > I didn't have used Ruby at that time.... I started programming Ruby > > about three days ago... and now look at this group.... > > ...and again find this "duck type". > > > > The things I read about it ("duck typing") when I first > > had contact to this item seem to be very similar to > > type polymorphism of functional languages.... look at > > OCaml or haskell for example. > > I haven't seen anyone mention it, and I think it's important to know... > The name 'Duck Typing' comes from the saying "if it walks like a duck > and quacks like a duck, it must be a duck." > (http://peak.telecommunity.com/DevCenter/MonkeyTyping) > > In short, if a type/class/whatever has all the methods of a duck (that > you intend to use), it's a duck and can be used as a duck would be used, > regardless of what's actually under the feathers. Yes. > In other words, TCPSocket doesn't just inherit from Socket, Object, > etc... It IS a Socket, it IS an Object, etc. While this is true, it's not a particularly good example to explain duck typing. Duck typing is not about what an object "is", but what it can be used for. Whether an object can be used for something depends on who is using it. Let's look at DT's example from the Pickaxe. Cutting the code down to the bare essentials we've got: def csv_from_row(op, row) #code to compute res from row op << res << CRLF end Now what kind of duck does op need to be? Simply an object which accumulates objects via the << method. His first use was: result = "" query.each_row {|row| csv_from_row(result, row) http.write result This works, Strings meet the requirements of the op parameter, but they also have other characteristics. The important one here is the subtle effect on GC. For a more detailed analysis of this see why's article http://whytheluckystiff.net/articles/theFullyUpturnedBin.html So let's try to find another object which we can put in the role of the op parameter. Arrays also can be used. So we have result = [] query.each_row {|row| csv_from_row(result, row) http.write result However we've now got a little problem in that although an array works as the op parameter, http.write probably won't like it. But that's easy to fix: http.write result.join Back when I was younger, and object[-oriented] programming was fairly new, my friends and I spent a lot of time philosophizing about types and objects. Although I don't remember talking about ducks, we did talk alot about the theater. The most common word we used to use for what we now call a duck type was a role. So when we duck type, we're in a position similar to a director casting for a role in a play. Sometimes, we find a great actor, but we need to subtly adapt the script to fit his style. That's what's happening in DT's pickaxe example. Another way of looking at this, is that duck typing is akin to the way the American President is chosen. An assessment is performed on the candidates, and then the country and world adapts. Contrast this to the way things are done in picking the next British monarch, or the type systems of C++ or Java. In both cases one has to be born into the role, having the right genes via inheritance. Of course in the first case, who gets the job doesn't matter all that much anymore. -- Rick DeNatale My blog on Ruby http://talklikeaduck.denhaven2.com/