Jump to page: 1 2 3
Thread overview
COMMENTS: Mixins Specification
Apr 30, 2004
fred
Apr 30, 2004
J Anderson
Apr 30, 2004
Matthew
Apr 30, 2004
Hauke Duden
Apr 30, 2004
Matthew
Apr 30, 2004
Hauke Duden
Apr 30, 2004
Matthew
Apr 30, 2004
Hauke Duden
Apr 30, 2004
J Anderson
Apr 30, 2004
Matthew
Apr 30, 2004
J Anderson
Apr 30, 2004
Patrick Down
Apr 30, 2004
Matthew
Apr 30, 2004
Ben Hinkle
May 01, 2004
Matthew
May 05, 2004
Russ Lewis
May 05, 2004
Russ Lewis
May 05, 2004
Matthew
May 05, 2004
Russ Lewis
May 05, 2004
Matthew
April 30, 2004
I would like to proposed the following specification for Mixins be included as part of Version 1.0 D Programming Language specification. All comments are welcomed.

MIXINS SPECIFICATION      Version 0.1

Introduction
What are mixins ?
A mixin is a class-like entity whose methods/fields are mixed-in to the mixing class just
as if the author of that class had written them manually.
As Matthew so neatly put it (see http://www.digitalmars.com/drn-bin/wwwnews?D/28348 )

Why do we need them ?
The rational for Mixins is quite compelling...
One of the greatest shortcomings of the C++ language from a Object Oriented perspective,
is that there is no language support for Aggregated Objects. As such, Aggregation has to be
performed programatically, often (incorrectly) using the inheritance mechanism as a coding
shortcut. By including language support we provide a direct correlation between OOD using
modeling techniques like UML, and OOP.

Background
Please read the following;
http://www.digitalmars.com/drn-bin/wwwnews?D/28455
http://www.digitalmars.com/drn-bin/wwwnews?D/28511
http://www.digitalmars.com/drn-bin/wwwnews?D/28553

Lexical
I propose that we use one of the two remaining (common) symbols, i.e. # and @ as well as
the keyword mixin. For this document we'll use # as the mixin symbol

Syntax
There are a number of syntax alternatives that could be incorporated.

Alternative A:
class <identifier> [: <inherited-class>]
                   [# <aggregated-class> <local-identifier>]*

For example;
class Lamp : Light
           # Body      cBody
           # Switch    cSwitch
           # Globe     cGlobe
           # PowerCord cPowerCord
{
    this() {
        super();
        cBody();                     // Body construction
        cGlobe();                    // Globe construction
        cPowerCord();                // PowerCord construction
        cSwitch(cGlobe,cPowerCord);  // Switch construction
    }
};

Alternative B:
class <identifier> [: <inherited-class>]
                   [# <aggregated-class> <local-identifier>
                   [, <aggregated-class> <local-identifier>]*]

For example;

class Lamp : Light
           # Body      cBody
           , Switch    cSwitch
           , Globe     cGlobe
           , PowerCord cPowerCord
{
    this() {
        super();
        cBody();                     // Body construction
        cGlobe();                    // Globe construction
        cPowerCord();                // PowerCord construction
        cSwitch(cGlobe,cPowerCord);  // Switch construction
    }
};

Semantics
The rules for Mixin variables should be the same as class member declarations, except
Mixins allow the interfaces of the aggregated class to be included as part of the mixing class.
This fact means that it is possible to have multiple versions of the same member name
within a mixing class.

I propose a simple precedence rule, where the member defined in the class overrides those defined in the aggregated class, and those in the aggregated classes are assigned according to the order they are declared. If this was to take place, a compiler warning message stating "that member X of aggregated class A is taking precedence over that in aggregated class B" should be displayed in the error log.

Note: there are probably other things that will need to be considered here !

Conclusion
Mixins permit externally declare classes to be used as part of a class, and in so doing provides
a real alternative to the Multiple Inheritance option provided for in the C++ language. As such, this
relatively insignificant addition to the language should greatly enhance the overall flexibility of the
D Programming Language.

Comments !


April 30, 2004
fred wrote:

> I would like to proposed the following specification for Mixins be included as part of Version 1.0
> D Programming Language specification. /All comments are welcomed./

I added this to http://www.prowiki.org/wiki4d/wiki.cgi?FeatureRequestList/Mixins.

-- 
-Anderson: http://badmama.com.au/~anderson/
April 30, 2004
Wow, I hadn't realised that this had got so serious!

I've been chatting with Walter about a mixins syntax to serve the needs of DTL, but had (carelessly / selfishly / stupidly / ...) not put it up on the group, as I didn't have time for a debate (which I still don't).

Roughly, here's my proposal, which, at first glance, appears to be quite a different kettle of fish to what you're talking about:

// - Mixins define class/instance methods.
// - Mixins do not define *any* instance fields. (Not sure about static fields -
what do you think?)
// - Mixin methods are added into the mixing class as if the user had typed them
in
// - Mixins have *no* polymorphic aspects whatsoever. Two classes that each mix
//   the same mixin are nonetheless completely unrelated
// - Mixin methods may "become" polymorphic with respect to any interface(s) that
the mixing class is "implement"ing
// - If the mixing class already contains a method of the same signature, that
"overrides" - prevents incorporation - of that mixin method.

Syntax:

mixin Ranges(C) // C is the mixing class.
{
private:
    typedef C.value_type    value_type; // A convenience for the mixin
implementation, and also a constraint on C
    typedef C.index_type    index_type; // A convenience for the mixin
implementation, and also a constraint on C

public:
    boolean contains(value_type comperand)
    {
        foreach(value_type v; cast(C)(this)) // How to get to the real, gestalt,
entity. foreach acts as a constraint on C
        {
            if(v == comperand)
            {
                return cast(boolean)(true);
            }
        }

        return cast(boolean)(false);
    }

    . . .
}

And is used as follows (as in the DTL classes, which require only that the mixing class has value_type and index_type member types, and be freachable):

template List(T, B = EmptyBase)
{
    public class List
        : B                      // base class
        , mixes Ranges    // Note: do not need to specify mixing class, since it
cannot be ambiguous.
    {
    }
}

Note that a mixin could also be a template, but needn't be. In a sense, it's already a template, as it's parameterised by one (and only one) type, its mixing class.

Clearly, there are some differences between your proposal and mine:

minor:

- I don't like the syntax you propose (i.e. the #, @), but this is a pretty minor issue, and will be whatever Walter deems most unambiguous and easy to parse

major:

- you allow for mixins to provide fields
- you allow mixins to introduce a different polymorphic nature to their mixing
class
- you allow mixins to have constructors, which I do not

I disagree with all of these, since it seems that your mixin design is almost a halfway house between SI and MI and, although I understand the motivation, I think we'll be in murky territory.

Of course, my perspective may well be covered by my needs. ;)

Matthew



"fred" <info@fleet-manage.com> wrote in message
news:c6s9ck$7go$1@digitaldaemon.com...
I would like to proposed the following specification for Mixins be included as
part of Version 1.0
D Programming Language specification. All comments are welcomed.

MIXINS SPECIFICATION      Version 0.1

Introduction
What are mixins ?
A mixin is a class-like entity whose methods/fields are mixed-in to the mixing
class just
as if the author of that class had written them manually.
As Matthew so neatly put it (see
http://www.digitalmars.com/drn-bin/wwwnews?D/28348 )

Why do we need them ?
The rational for Mixins is quite compelling...
One of the greatest shortcomings of the C++ language from a Object Oriented
perspective,
is that there is no language support for Aggregated Objects. As such, Aggregation
has to be
performed programatically, often (incorrectly) using the inheritance mechanism as
a coding
shortcut. By including language support we provide a direct correlation between
OOD using
modeling techniques like UML, and OOP.

Background
Please read the following;
http://www.digitalmars.com/drn-bin/wwwnews?D/28455
http://www.digitalmars.com/drn-bin/wwwnews?D/28511
http://www.digitalmars.com/drn-bin/wwwnews?D/28553

Lexical
I propose that we use one of the two remaining (common) symbols, i.e. # and @ as
well as
the keyword mixin. For this document we'll use # as the mixin symbol

Syntax
There are a number of syntax alternatives that could be incorporated.

Alternative A:
class <identifier> [: <inherited-class>]
                   [# <aggregated-class> <local-identifier>]*

For example;
class Lamp : Light
           # Body      cBody
           # Switch    cSwitch
           # Globe     cGlobe
           # PowerCord cPowerCord
{
    this() {
        super();
        cBody();                     // Body construction
        cGlobe();                    // Globe construction
        cPowerCord();                // PowerCord construction
        cSwitch(cGlobe,cPowerCord);  // Switch construction
    }
};

Alternative B:
class <identifier> [: <inherited-class>]
                   [# <aggregated-class> <local-identifier>
                   [, <aggregated-class> <local-identifier>]*]

For example;

class Lamp : Light
           # Body      cBody
           , Switch    cSwitch
           , Globe     cGlobe
           , PowerCord cPowerCord
{
    this() {
        super();
        cBody();                     // Body construction
        cGlobe();                    // Globe construction
        cPowerCord();                // PowerCord construction
        cSwitch(cGlobe,cPowerCord);  // Switch construction
    }
};

Semantics
The rules for Mixin variables should be the same as class member declarations,
except
Mixins allow the interfaces of the aggregated class to be included as part of the
mixing class.
This fact means that it is possible to have multiple versions of the same member
name
within a mixing class.

I propose a simple precedence rule, where the member defined in the class
overrides those
defined in the aggregated class, and those in the aggregated classes are assigned
according
to the order they are declared. If this was to take place, a compiler warning
message stating
"that member X of aggregated class A is taking precedence over that in aggregated
class B"
should be displayed in the error log.

Note: there are probably other things that will need to be considered here !

Conclusion
Mixins permit externally declare classes to be used as part of a class, and in so
doing provides
a real alternative to the Multiple Inheritance option provided for in the C++
language. As such, this
relatively insignificant addition to the language should greatly enhance the
overall flexibility of the
D Programming Language.

Comments !


April 30, 2004
Matthew wrote:

> Wow, I hadn't realised that this had got so serious!
> 
> I've been chatting with Walter about a mixins syntax to serve the needs of DTL,
> but had (carelessly / selfishly / stupidly / ...) not put it up on the group, as
> I didn't have time for a debate (which I still don't).
> 
> Roughly, here's my proposal, which, at first glance, appears to be quite a
> different kettle of fish to what you're talking about:
> 
> // - Mixins define class/instance methods.
> // - Mixins do not define *any* instance fields. (Not sure about static fields -
> what do you think?)
> // - Mixin methods are added into the mixing class as if the user had typed them
> in
> // - Mixins have *no* polymorphic aspects whatsoever. Two classes that each mix
> //   the same mixin are nonetheless completely unrelated
> // - Mixin methods may "become" polymorphic with respect to any interface(s) that
> the mixing class is "implement"ing
> // - If the mixing class already contains a method of the same signature, that
> "overrides" - prevents incorporation - of that mixin method.

I like it. It is simple and exactly what you need to put mixins to good use. Especially the fact that it doesn't change the classes type will prevent a lot of headaches.

One other thing may be important, though. I think mixins should be combinable to form new mixins (i.e. some kind of multiple inheritance between mixins but without any type issues). I mostly want mixins to be able to conveniently provide default implementations for interfaces. And since interfaces form a hierarchy, the implementations of more specialized interfaces could then re-use implementations of the general interfaces.

The implementation shouldn't be much of a problem since mixins are "typeless", so there can be none of that multiple inheritance chaos we know from C++. It would be the same as simply copying all the code from the different mixins into a new mixin, but allowing the newly created mixin to overwrite methods already defined in one of the base mixins.

Note that this simply means that mixins can mix-in other mixins in the same way that classes can.

Example:

mixin A(X) {...}
mixin B(X) {...}

mixin C(X) mixes A,B {...}

April 30, 2004
Matthew wrote:

>Wow, I hadn't realised that this had got so serious!
>
>I've been chatting with Walter about a mixins syntax to serve the needs of DTL,
>but had (carelessly / selfishly / stupidly / ...) not put it up on the group, as
>I didn't have time for a debate (which I still don't).
>
>Roughly, here's my proposal, which, at first glance, appears to be quite a
>different kettle of fish to what you're talking about:
>
>// - Mixins define class/instance methods.
>// - Mixins do not define *any* instance fields. (Not sure about static fields -
>what do you think?)
>// - Mixin methods are added into the mixing class as if the user had typed them
>in
>// - Mixins have *no* polymorphic aspects whatsoever. Two classes that each mix
>//   the same mixin are nonetheless completely unrelated
>// - Mixin methods may "become" polymorphic with respect to any interface(s) that
>the mixing class is "implement"ing
>// - If the mixing class already contains a method of the same signature, that
>"overrides" - prevents incorporation - of that mixin method.
>
>Syntax:
>
>mixin Ranges(C) // C is the mixing class.
>{
>private:
>    typedef C.value_type    value_type; // A convenience for the mixin
>implementation, and also a constraint on C
>    typedef C.index_type    index_type; // A convenience for the mixin
>implementation, and also a constraint on C
>
>public:
>    boolean contains(value_type comperand)
>    {
>        foreach(value_type v; cast(C)(this)) // How to get to the real, gestalt,
>entity. foreach acts as a constraint on C
>        {
>            if(v == comperand)
>            {
>                return cast(boolean)(true);
>            }
>        }
>
>        return cast(boolean)(false);
>    }
>
>    . . .
>}
>
>And is used as follows (as in the DTL classes, which require only that the mixing
>class has value_type and index_type member types, and be freachable):
>
>template List(T, B = EmptyBase)
>{
>    public class List
>        : B                      // base class
>        , mixes Ranges    // Note: do not need to specify mixing class, since it
>cannot be ambiguous.
>    {
>    }
>}
>
>Note that a mixin could also be a template, but needn't be. In a sense, it's
>already a template, as it's parameterised by one (and only one) type, its mixing
>class.
>
>Clearly, there are some differences between your proposal and mine:
>
>minor:
>
>- I don't like the syntax you propose (i.e. the #, @), but this is a pretty minor
>issue, and will be whatever Walter deems most unambiguous and easy to parse
>
>major:
>
>- you allow for mixins to provide fields
>- you allow mixins to introduce a different polymorphic nature to their mixing
>class
>- you allow mixins to have constructors, which I do not
>
>I disagree with all of these, since it seems that your mixin design is almost a
>halfway house between SI and MI and, although I understand the motivation, I
>think we'll be in murky territory.
>
>Of course, my perspective may well be covered by my needs. ;)
>
>Matthew
>  
>

Just out of interest: It appears to me that mixins (the class part) are very similar to structs?  Why couldn't structs be used as mixins instead?

I mean something like:

struct Ranges(C) // C is the mixing class.
{
private:
   typedef C.value_type    value_type; // A convenience for the mixin
implementation, and also a constraint on C
   typedef C.index_type    index_type; // A convenience for the mixin
implementation, and also a constraint on C

public:
   boolean contains(value_type comperand)
   {
       foreach(value_type v; cast(C)(this)) // How to get to the real, gestalt,
entity. foreach acts as a constraint on C
       {
           if(v == comperand)
           {
               return cast(boolean)(true);
           }
       }

       return cast(boolean)(false);
   }

   . . .
}


template List(T, B = EmptyBase)
{
   public class List
       : B                      // base class
       , mixes Ranges    // Note: do not need to specify mixing class, since it
cannot be ambiguous.
   {
   }
}


-- 
-Anderson: http://badmama.com.au/~anderson/
April 30, 2004
"Hauke Duden" <H.NS.Duden@gmx.net> wrote in message news:c6t7gs$1m30$1@digitaldaemon.com...
> Matthew wrote:
>
> > Wow, I hadn't realised that this had got so serious!
> >
> > I've been chatting with Walter about a mixins syntax to serve the needs of
DTL,
> > but had (carelessly / selfishly / stupidly / ...) not put it up on the group,
as
> > I didn't have time for a debate (which I still don't).
> >
> > Roughly, here's my proposal, which, at first glance, appears to be quite a different kettle of fish to what you're talking about:
> >
> > // - Mixins define class/instance methods.
> > // - Mixins do not define *any* instance fields. (Not sure about static
fields -
> > what do you think?)
> > // - Mixin methods are added into the mixing class as if the user had typed
them
> > in
> > // - Mixins have *no* polymorphic aspects whatsoever. Two classes that each
mix
> > //   the same mixin are nonetheless completely unrelated
> > // - Mixin methods may "become" polymorphic with respect to any interface(s)
that
> > the mixing class is "implement"ing
> > // - If the mixing class already contains a method of the same signature,
that
> > "overrides" - prevents incorporation - of that mixin method.
>
> I like it. It is simple and exactly what you need to put mixins to good use. Especially the fact that it doesn't change the classes type will prevent a lot of headaches.
>
> One other thing may be important, though. I think mixins should be combinable to form new mixins (i.e. some kind of multiple inheritance between mixins but without any type issues). I mostly want mixins to be able to conveniently provide default implementations for interfaces. And since interfaces form a hierarchy, the implementations of more specialized interfaces could then re-use implementations of the general interfaces.
>
> The implementation shouldn't be much of a problem since mixins are "typeless", so there can be none of that multiple inheritance chaos we know from C++. It would be the same as simply copying all the code from the different mixins into a new mixin, but allowing the newly created mixin to overwrite methods already defined in one of the base mixins.
>
> Note that this simply means that mixins can mix-in other mixins in the same way that classes can.
>
> Example:
>
> mixin A(X) {...}
> mixin B(X) {...}
>
> mixin C(X) mixes A,B {...}

That seems reasonable, except where they had methods with the same signatures. I don't like the DAG crap that would transpire as a result.



April 30, 2004
"J Anderson" <REMOVEanderson@badmama.com.au> wrote in message news:c6t9ri$1pfq$1@digitaldaemon.com...
> Matthew wrote:
>
> >Wow, I hadn't realised that this had got so serious!
> >
> >I've been chatting with Walter about a mixins syntax to serve the needs of
DTL,
> >but had (carelessly / selfishly / stupidly / ...) not put it up on the group,
as
> >I didn't have time for a debate (which I still don't).
> >
> >Roughly, here's my proposal, which, at first glance, appears to be quite a different kettle of fish to what you're talking about:
> >
> >// - Mixins define class/instance methods.
> >// - Mixins do not define *any* instance fields. (Not sure about static
fields -
> >what do you think?)
> >// - Mixin methods are added into the mixing class as if the user had typed
them
> >in
> >// - Mixins have *no* polymorphic aspects whatsoever. Two classes that each
mix
> >//   the same mixin are nonetheless completely unrelated
> >// - Mixin methods may "become" polymorphic with respect to any interface(s)
that
> >the mixing class is "implement"ing
> >// - If the mixing class already contains a method of the same signature, that
> >"overrides" - prevents incorporation - of that mixin method.
> >
> >Syntax:
> >
> >mixin Ranges(C) // C is the mixing class.
> >{
> >private:
> >    typedef C.value_type    value_type; // A convenience for the mixin
> >implementation, and also a constraint on C
> >    typedef C.index_type    index_type; // A convenience for the mixin
> >implementation, and also a constraint on C
> >
> >public:
> >    boolean contains(value_type comperand)
> >    {
> >        foreach(value_type v; cast(C)(this)) // How to get to the real,
gestalt,
> >entity. foreach acts as a constraint on C
> >        {
> >            if(v == comperand)
> >            {
> >                return cast(boolean)(true);
> >            }
> >        }
> >
> >        return cast(boolean)(false);
> >    }
> >
> >    . . .
> >}
> >
> >And is used as follows (as in the DTL classes, which require only that the
mixing
> >class has value_type and index_type member types, and be freachable):
> >
> >template List(T, B = EmptyBase)
> >{
> >    public class List
> >        : B                      // base class
> >        , mixes Ranges    // Note: do not need to specify mixing class, since
it
> >cannot be ambiguous.
> >    {
> >    }
> >}
> >
> >Note that a mixin could also be a template, but needn't be. In a sense, it's already a template, as it's parameterised by one (and only one) type, its
mixing
> >class.
> >
> >Clearly, there are some differences between your proposal and mine:
> >
> >minor:
> >
> >- I don't like the syntax you propose (i.e. the #, @), but this is a pretty
minor
> >issue, and will be whatever Walter deems most unambiguous and easy to parse
> >
> >major:
> >
> >- you allow for mixins to provide fields
> >- you allow mixins to introduce a different polymorphic nature to their mixing
> >class
> >- you allow mixins to have constructors, which I do not
> >
> >I disagree with all of these, since it seems that your mixin design is almost
a
> >halfway house between SI and MI and, although I understand the motivation, I think we'll be in murky territory.
> >
> >Of course, my perspective may well be covered by my needs. ;)
> >
> >Matthew
> >
> >
>
> Just out of interest: It appears to me that mixins (the class part) are very similar to structs?  Why couldn't structs be used as mixins instead?

Because a struct does not have a mixing class. If you made the struct a template, that would mean that mixins could not be templates - which they can in my proposal - because the "template" syntax would already be used in making it a mixin.

There are several other reasons why it can't be so, but that's good enough.

>
> I mean something like:
>
> struct Ranges(C) // C is the mixing class.
> {
> private:
>     typedef C.value_type    value_type; // A convenience for the mixin
> implementation, and also a constraint on C
>     typedef C.index_type    index_type; // A convenience for the mixin
> implementation, and also a constraint on C
>
> public:
>     boolean contains(value_type comperand)
>     {
>         foreach(value_type v; cast(C)(this)) // How to get to the real,
gestalt,
> entity. foreach acts as a constraint on C
>         {
>             if(v == comperand)
>             {
>                 return cast(boolean)(true);
>             }
>         }
>
>         return cast(boolean)(false);
>     }
>
>     . . .
> }
>
>
> template List(T, B = EmptyBase)
> {
>     public class List
>         : B                      // base class
>         , mixes Ranges    // Note: do not need to specify mixing class, since
it
> cannot be ambiguous.
>     {
>     }
> }
>
>
> -- 
> -Anderson: http://badmama.com.au/~anderson/


April 30, 2004
Matthew wrote:

>>Just out of interest: It appears to me that mixins (the class part) are
>>very similar to structs?  Why couldn't structs be used as mixins instead?
>>    
>>
>
>Because a struct does not have a mixing class. If you made the struct a template,
>that would mean that mixins could not be templates - which they can in my
>proposal - because the "template" syntax would already be used in making it a
>mixin.
>
>There are several other reasons why it can't be so, but that's good enough.
>  
>
I thought there was a reason, thanks.

-- 
-Anderson: http://badmama.com.au/~anderson/
April 30, 2004
In article <c6sb58$a39$1@digitaldaemon.com>, Matthew says...
>
>Wow, I hadn't realised that this had got so serious!
>
>I've been chatting with Walter about a mixins syntax to serve the needs of DTL, but had (carelessly / selfishly / stupidly / ...) not put it up on the group, as I didn't have time for a debate (which I still don't).

Real work has been keeping me busy for 14 days straight here but I will make a few comments.

>
>Roughly, here's my proposal, which, at first glance, appears to be quite a different kettle of fish to what you're talking about:
>
>// - Mixins define class/instance methods.
>// - Mixins do not define *any* instance fields. (Not sure about static fields -
>what do you think?)

This seems a little arbitrary.  Why should this restriction be made especially give the implementation just below.  I can think of a number of reason to want fields.

>// - Mixin methods are added into the mixing class as if the user had typed them in

Yes

>// - Mixins have *no* polymorphic aspects whatsoever. Two classes that each mix //   the same mixin are nonetheless completely unrelated

Yes

>// - Mixin methods may "become" polymorphic with respect to any interface(s) that
>the mixing class is "implement"ing
>// - If the mixing class already contains a method of the same signature, that
>"overrides" - prevents incorporation - of that mixin method.

Does this include methods from a base of the class?  I would say that any directly defined members of the class take precedence over the mixin method but the mixin method take precedence over and base class method.

My view point on mixins is in line with Fred's post.  ( See my reply to him. )  The major difference is that I think the mixin declaration needs to go into the class body not the header.  The reason for this is that I think mixins should be able to be able to be parameterized by items from the declaration scope.













April 30, 2004
Matthew wrote:
>>Note that this simply means that mixins can mix-in other mixins in the
>>same way that classes can.
>>
>>Example:
>>
>>mixin A(X) {...}
>>mixin B(X) {...}
>>
>>mixin C(X) mixes A,B {...}
> 
> 
> That seems reasonable, except where they had methods with the same signatures. I
> don't like the DAG crap that would transpire as a result.

I think the same rules that are used when a class uses multiple mixins should apply. How is it handled there?

The optimal thing would be if such conflicts are silently ignored if the function's code is the same in all mixins. Might be a little complicated to implement though (or it may be a simple memcmp - probably only Walter knows).

Otherwise I see two solutions:

1) it is an error and the class must override such functions

2) use a simple precedence rule, like first mixin wins (according to the order in which they are mentioned in the class definition). I like this one because of its simplicity. One could argue that it can hide mistakes, but it is basically the same thing as the rule that class methods win over mixin methods. I.e. "read the class definition from left to right and use the first matching method you find in the mentioned entities".

Hauke
« First   ‹ Prev
1 2 3