...
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:
...
Code Block |
---|
def SomePythonFunction (s, i):
print i
return i + 3
{code}
|
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
...
Name
...
property:
...
Code Block |
---|
def SomeDumperFunction (obj):
print obj.Name
{code}
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 {{Person}} objects, {{File}} objects, {{Pet}} objects as {{obj}} and {{SomeDumperFunction}} will happily evaluate {{.Name}} at run-time, not caring about {{obj}}'s type.
The {{Person}}\-, {{File}}\- and {{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 {{Name}} property.
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.
h5. 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
{code} |
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 Person
objects, File
objects, Pet
objects as obj
and SomeDumperFunction
will happily evaluate .Name
at run-time, not caring about obj
's type.
The Person
-, File
- and 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 Name
property.
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
Code Block |
---|
class Foo : IBar, IBaz
{code}
|
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
...
...
.
...
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
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
.
...
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
...
...
...
...
...
...
...
...
...
...
...
...
.
...
]
...
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, Person
and Parrot
have no common ancestor. Here is the Person
class:
Code Block |
---|
public class Person
{
public string FirstName { get; set; }
public string Surname { get; set; }
public virtual void Say (string s)
{
// an artificially awkward implementation
// to show that this 'Say' is TOTALLY unlike
// 'Parrot's 'Say'
foreach (var c in s)
{
Console.Write (c);
}
}
}
{code}
|
If
...
we
...
want
...
to
...
give
...
our
...
Person
...
acting
...
capabilities
...
for
...
performing
...
a
...
short
...
dialog
...
on
...
the
...
phone,
...
we
...
can
...
extend
...
it
...
with
...
the
...
OnThePhoneMixin
...
.
...
To
...
this
...
end,
...
we
...
could
...
use
...
the
...
IParrot
...
interface
...
from
...
the
...
previous
...
page.
...
However,
...
it
...
is
...
more
...
appropriate
...
to
...
rename
...
that
...
interface
...
to
...
ISpeaker
...
:
...
Code Block |
---|
public interface ISpeaker
{
void Say (string s);
}
{code}
|
Again,
...
it
...
is
...
NOT
...
necessary
...
to
...
declare
...
Person
...
or
...
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
...
Mixin<TThis>
...
:
...
Code Block |
---|
[Extends (typeof (Parrot))]
[Extends (typeof (Person))]
public class OnThePhoneMixin : Mixin<ISpeaker>, IOnThePhoneMixin
{
public void PretendToTalkOnThePhone ()
{
This.Say ("Ring ring");
This.Say ("Ring ring");
This.Say ("Halloho?");
Wait (1500);
This.Say ("Oh! Hi!");
Wait (3000);
This.Say ("I'm fine! And yourself?");
Wait (1500);
This.Say ("Glad to hear that! I love you! Bye!");
}
public void Wait (int milliSeconds)
{
Thread.Sleep (milliSeconds);
}
}
{code}
|
The
...
declaration
...
listed
...
above
...
extends
...
both
...
Parrot
...
and
...
Person
...
with
...
the
...
OnThePhone
...
feature,
...
although
...
these
...
classes
...
have
...
nothing
...
in
...
common
...
and
...
don't
...
even
...
implement
...
the
...
ISpeaker
...
interface.
...
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
...
OnThePhone
...
's
...
Say
...
is
...
delegated
...
to
...
the
...
target
...
class'
...
Say
...
.
...
Here
...
is
...
client
...
code
...
for
...
convincing
...
yourself
...
that
...
this
...
actually
...
works:
...
Code Block |
---|
// you must force the .NET runtime to load a reference to the
// Remotion.dll assembly. Otherwise the compiler will remove the
// facilities for loading the Remotion.dll assembly and your application
// will throw a type initializer exception, because it can't load it.
// The easiest way to touch the assembly is to use the IMixinTarget
// identifier:
FrameworkVersion.RetrieveFromType (typeof (IMixinTarget));
// instantiate parrot thespian
var myPetParrot = ObjectFactory.Create<Parrot> (ParamList.Empty);
Console.WriteLine ("Parrot:");
((IOnThePhoneMixin) myPetParrot).PretendToTalkOnThePhone ();
Console.WriteLine ();
// instantiate person thespian
var myPetPerson = ObjectFactory.Create<Person> (ParamList.Empty);
Console.WriteLine ("Person");
((IOnThePhoneMixin) myPetPerson).PretendToTalkOnThePhone ();
Console.ReadLine ();
{code}
h5. Sample code
The sample code for this |
Sample code
The sample code for this wiki-page
...
is
...
located
...
...
...
.
...