Duck typing

From Wikipedia, the free encyclopedia

In computer science, duck typing is a form of dynamic typing in which a variable's value itself implicitly determines what the variable can do. This implies that an object is interchangeable with any other object that implements the same interface, regardless of whether the objects have a related inheritance hierarchy. Duck typing is a feature of programming languages such as Smalltalk, Python, Ruby, JavaScript, and ColdFusion.

The term is a reference to the duck test — "If it walks like a duck and quacks like a duck, it must be a duck". Alex Martelli is thought to have originated the term in a message to the comp.lang.python newsgroup. However, the concept has use in the operational framework with its increasing reliance on computing.[citation needed]

In Smalltalk, any object is interchangeable with any other at runtime. This is the most flexible kind of dynamic typing. Duck typing attempts to limit this flexibility while eliminating a source of possible errors before runtime. The Smalltalk architects sought to achieve true polymorphism at the expense of possible errors creeping in at runtime. In practice, these errors are dealt with, at runtime, via SUnit testing.

Abstract data types are static interfaces that exist only to guarantee, on paper, a particular interface. Smalltalk uses pure dynamic mechanisms, in a variety of ways, to extend the guarantee in practice. This can be as simple as generalizing the "method not found" exception handler into a catch-all lookup mechanism. But it can involve extending the language or environment, as in StrongTalk. Parallels to Smalltalk's exception handling came to be called duck typing in Java and Python, and a single reasonable syntax emerged.

C++ templates implement a static form of duck typing. An iterator, for example, does not inherit its methods from an Iterator base class.

Yet another approach similar to duck typing is OCaml's structural subtyping, where object types are compatible if their method signatures are compatible, regardless of their declared inheritance. This is all detected at compile time through OCaml's type inference system.

Contents

[edit] In Ruby

Duck typing is a fundamental part of ruby coding. The pickaxe book (Programming Ruby), written by Dave Thomas, has a more complete description of duck typing, explaining its perils and benefits.

[edit] In Python

Duck typing is heavily used in Python. The Python Tutorial's Glossary defines duck typing as follows:

Pythonic programming style that determines an object's type by inspection of its method or attribute signature rather than by explicit relationship to some type object ("If it looks like a duck and quacks like a duck, it must be a duck.") By emphasizing interfaces rather than specific types, well-designed code improves its flexibility by allowing polymorphic substitution. Duck-typing avoids tests using type() or isinstance(). Instead, it typically employs hasattr() tests or EAFP (Easier to Ask Forgiveness than Permission) programming.

The standard example of duck typing in Python is file-like classes. Classes can implement some or all of the methods of file and can be used where file would normally be used. For example, GzipFile implements a file-like object for accessing gzip-compressed data. cStringIO allows treating a Python string as a file. Sockets and files share many of the same methods as well. However, sockets lack the tell() method and cannot be used everywhere that GzipFile can be used. This shows the flexibility of duck typing: a file-like object can implement only methods it is able to, and consequently it can be only used in situations where it makes sense.

[edit] In Java

In 2003, Dave Orme, leader of Eclipse's Visual Editor Project was looking for a generic way to bind any SWT (Standard Widget Toolkit) control to any JavaBeans-style object. He noticed that SWT reuses names religiously across its class hierarchy. For example, to set the caption of something, you normally set the Text property. This is true for an SWT Shell (window), a Text control, a Label, and many more SWT controls. Orme realized that if he could implement data binding in terms of the methods that are implemented on a control, he would save considerable work and achieve a much higher level of code reuse, compared to implementing separate data binding for an SWT Shell, Text, Label, and so on. When the Ruby community started describing this kind of type system as "duck typing", Orme realized that he had simply rediscovered what Smalltalk, Ruby, Python and other programmers had already known for a long time.

Orme formalized this knowledge by creating a class that makes duck typing simple and natural for Java programmers (see "Java Does Duck Typing"). Cedric Beust later cautioned about possible dangers using duck typing in "The Perils of Duck Typing".

Note that even in the absence of duck typing, you can still use the Adapter Pattern to make instances conform to given interfaces. The generation of adapters can be automated using dynamic code generation [1], a process that is also used in implementations of duck-typed languages on top of the JVM.

[edit] In Objective-C

In Objective-C you can refer to a class using the type(less) id. The RTE will map a message to such an object by resolving the adequate method without checking for a type. The question, whether an object has a method for a message is not a question of class.

You can send such a message explicitly or implicitly:

id anObject = … // An object of any class implementing -walkAndQuack

[anObject walkAndQuack]; // implicit call
[anObject performSelector:@selector( walkAndQuack )]; // explicit call

You can check at run-time, whether a particular method is implemented using -respondsToSelector:.

Cocoa is using this feature for example, when it asks several objects (Application, View, Window), whether a user interaction can be performed.

[edit] In ColdFusion

ColdFusion, a web application scripting language, also allows duck typing although the technique is still fairly new to the ColdFusion developer community. Function arguments can be specified to be of type any so that arbitrary objects can be passed in and then method calls are bound dynamically at runtime. If an object does not implement a called method, a runtime exception is thrown which can be caught and handled gracefully. An alternative argument type of WEB-INF.cftags.component restricts the passed argument to be a ColdFusion Component (CFC), which provides better error messages should a non-object be passed in.

[edit] Comparison with generics and structural subtyping

In C++ and some other languages, very flexible static binding capabilities, called generics, templates, and operator overloading, provide some of the same advantages, but typically not as late as run time. This static polymorphism is distinguished from runtime facilities for dynamic types.

[edit] Biological classification analogy

By analogy with scientific classification in biology, duck typing is a morphogenetic classification scheme. Object-oriented languages that use classical inheritance tend to take a phylogenetic approach to structuring software systems; that is, they classify objects in terms of their inheritance, or "is-a" relationships, and only objects of the same lineage can be substituted polymorphically.

Some languages, however, including those that use duck typing, allow morphogenetic classification; that is, they allow classification of objects in terms of their "shape" or how they "look". In software object terms, an object's "shape" is determined by its declared interface(s) (for example, in Java) or by the operations it supports (in duck typed languages). In duck typing, the actual inheritance of an object (or phylogeny) is of less importance than the way it "looks" (or morphology) to users of the object. Duck typing represents a relatively pure form of morphogenetic classification in which sets of coincident operations form ad hoc interfaces, versus semi-morphogenetic classification based on statically declared interfaces, like in Java.

[edit] External links

In other languages