On Mixins, Multiple Inheritance and behavioural composition

5 views
Skip to first unread message

Rick Moynihan

unread,
Feb 19, 2009, 7:07:20 PM2/19/09
to scottish-...@googlegroups.com
Hi all,

Well, after attending Collins flash talk yesterday; on attempting to
hack mixins into C#, I thought I'd drop an email to the list to
continue the discussions/debate and exploration of the topic a little
more.

For those who weren't there, Colin described an attempt to hack
mixin-like behavior into C#, using extension methods and interfaces.
I'm not a C# or .Net developer but am more than familiar enough with
Java and other languages to follow what he was doing.

Sadly I think we all (Colin included) found the ultimate
implementation lacking, a useful thought exercise that in the context
of C#, probably has more cons than pros.

For me, Colin's Mixins appeared to lack the essence of true mixins,
and I was unsure about what they were trying to achieve... When
pushed I was somewhat surprised at how everyone had different views
about the essential characteristics of what a mixin was, and how they
differed from MI. Colin saw the main difference as being able to
escape 'kind of' relationships between classes, i.e. the ability to
add a 'Flyable' mixin to a bird without saying that a bird is a kind
of Flyable; where as I saw mixins more as a means of escaping the
complexity of method resolution in multiple inheritance as found in
e.g. the Diamond Problem:
http://en.wikipedia.org/wiki/Diamond_problem.

The discussion prompted me to think some more about what a mixin truly
is, as I don't think any of us present fully described what they
were... I'm not sure I have a definitive answer yet; but here's my
shot at it... Hopefully others can join in for a friendly debate, or
exploration of this topic! :-)

When I think of Mixins, I naturally think of their uses in Ruby - the
language with mixins, with which I am most familiar. Despite being
familiar with them I couldn't recall quite how Mixins in Ruby had
access to the Mixee's state, so I eered on the side of caution and
said they didn't. This was patently wrong, they do... e.g.

# The Module to mixin
module Flyable
def fly(distance)
flapWings
@energy -= distance
end
end

# The mixee class
class Bird
attr_reader :energy
include Flyable
def initialize
@energy = 100
end

# ...

end

tweety = Bird.new
tweety.energy # => 100
tweety.fly 10
tweety.energy # => 90

Some of you might find this surprising, but in Ruby member variables
of an object (those preceeded with an @sign) can be declared
dynamically; i.e. they don't need to be declared before their first
use e.g.

class Foo
def initialize
# constructor (no member variables declared)
end

def foo
@foo = "foo bar!"
end
end

f = Foo.new # f contains no member variables
f.foo # f now contains a member variable initialised to "foo bar!"

When you consider this it's natural for mixins (in Ruby) to be able to
share state with the mixee... Naturally this isn't without
disadvantages, the main one being that member variables can collide
resulting in potentially incompatible mixins, in a way that is
somewhat analogous to unhygenic-macros in Common Lisp or Scheme.
There are ways to mitigate this, but sadly none as good as those in
the various forms of Lisp (gensym, let-syntax etc...).

These differ from Colins mixin's in that mixin's can share state
between methods within both the mixin and the class. Where as Colin's
mixin's are limited to essentially being stateless class methods,
somewhat akin to the following in Ruby:

module SexualReproduction
def mate(male,female)
self.new(male, female)
end
end

class Animal
extend SexualReproduction
end

class Dog < Animal
def initialize(male,female)
end
end

pup = Dog.mate(fido, lady)

Here Ruby's extend method allows you to mix methods from the module
into the class as class methods. Note that the above code is
essentially an Abstract Factory. Colin are your mixins capable of
this? At first I thought you might be able to, but now I'm thinking
C# will probably act like Java and prevent you from calling the
constructor due to constructors being undefinable on interfaces?

I realise this probably looks like language (or mixin) bashing... It's
not my intention, as I want to speak about them in the abstract sense.
Infact I guess that's another nature of the beast. They're abstract
collections of methods, and a useful complementary feature to classes;
as the main role of classes is as a creator of instances, which means
that they are required to be complete at instantiation time. Yet this
conflicts with the other role of a class as a unit of composition. So
is a key feature of mixins not the ability to have finer grained
composition due to the removal of the burden of instantiation?

Despite my love of mixins (and the hair raising world of meta
programming) I do get concerned about the potential for abuse, too
many mixins allows the construction of GodClasses, where the code is
fragmented into countless files. More concerning is the potential
for colliding member variables in Ruby. It seems like it might be
nice to support gensym or let-syntax constructs to allow safely shared
state within the mixin, but without potential collision. Does anyone
know of a language that does this?? I hear traits are supposed to
solve some problems with mixin's but haven't really looked at them
yet.

Comments, discussion and corrections, encouraged!! :-)

R.

Reply all
Reply to author
Forward
0 new messages