Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 4.0

...

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

...

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, 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

...

in

...

subversion

...

.

...