Duck typing in dynamic languages
What advocates of "dynamic" (dynamically typed) languages like about them is duck typing.
In python, for example, you can pass and return values of any type, the functions working with them don't care at compile type:
The result is less typing for data and less typing for fingers, but also more flexibility.
The disadvantage is that there is no guarantee that it is really an integer that is passed as
i, so the
+ 3 operation might fail at run-time. (This is less of a problem than most aficionados of static languages like C# assume, but the biggest disadvantage is this: static compilers can safely remove all sorts of run-time checks and gain more insights into the programmer's intention. A compiler for a statically typed language gives you faster code.)
The lack of static typing at compile time comes with an added benefit – so-called "duck typing". Let's say your python function prints the string in a
If you pass an integer as
obj, this function will obviously fail, because an integer does not have a
Name property (called "attribute" in python).
On the plus side: WHATEVER has a
Name property will work, no matter of what type
obj is. Only the name is significant here. You can pass
Pet objects as
SomeDumperFunction will happily evaluate
.Name at run-time, not caring about
Pet classes don't need to be related in any way, namely, they don't need to be derived from a common base class sporting that
In other words: whatever works out syntactically at run-time (based solely on identifiers) is good to go for evaluation.
This phenomenon resembles the old American proverb "Whatever looks like a duck, walks like a duck, quacks like a duck and swims like a duck is as cute as a duck", therefore: "duck typing".
Note that duck-typing makes interfaces obsolete, because no extra insulation or casts between "unrelated" types are required.
Duck-typing in re-motion mixins
Conversely, static languages provide some of duck-typing's flexibility with interfaces. Interfaces provide type-safety at compile-time and flexibility at run-time via casts to particular interfaces. This flexibility requires that the programmer signals to the compiler that a certain class implements one ore more specific interfaces, as in
What's more, languages like C# and Java provide powerful reflection – unlike the older, less abstract C and C++. Just like python (or ruby, or perl), C# can access functions, types and properties at run-time by name, although much more work is required to do so.
Reflection and code generation are used by re-mix. A byproduct of its design and implementation is form of duck-typing: you can tuck an interface to an implementation without accessing the implementation's source code. A target class like
Parrot does not need to know that somewhere in your source code there is an
IParrot interface that happens to include members that share the names and signatures with some or all in the target class. This feature is closely related to the discussion presented in re-motion mixins basics -- the 'Extends' attribute#Sneak preview on re-motion mixins and duck typing.
This can be very important for frameworks and classes for which you don't have access to the source code.
For best effect, imagine that you don't have source code for the involved target classes.
Duck-typing for pets
What if a new class of speakers enters our parrot architecture? [ The
Parrot class was introduced in re-motion mixins basics -- what about sub-classes of the target class?. ] All of a sudden, we not only have
Parrot who can say something, but also
Person. Persons can talk, so
Person has a
Say method, just like
Parrot. However, in our example,
Parrot have no common ancestor. Here is the
If we want to give our
Person acting capabilities for performing a short dialog on the phone, we can extend it with the
To this end, we could use the
IParrot interface from the previous page. However, it is more appropriate to rename that interface to
Again, it is NOT necessary to declare
Parrot to implement
ISpeaker for mixing. In this simple example, the mixin class does not override anything, so we can resort to the single-parameter
The declaration listed above extends both
Person with the
OnThePhone feature, although these classes have nothing in common and don't even implement the
ISpeaker, passed as
TThis parameter to
Mixin<TThis> provides only the information that the mixin class can expect the
Say method implementations SOMEWHERE in the target class. The eventual implementation, wiring up everything, in the mixed class is done at run-time. The mixer code will take care that
Say is delegated to the target class'
Say. Here is client code for convincing yourself that this actually works:
The sample code for this wiki-page is located in subversion.