www.digitalmars.com         C & C++   DMDScript  

D - D interfaces and mixins

reply "MikkelFJ" <mikkel dvideNOSPAMDOT.com> writes:
Walter asked me to post this on the newsgroup, my original mail below.

Note to below: Thinking some more about the sugg. about filtering mixins
through an interface, I think it will not work because mixins may also need
to include helper functions on non-public members i.e. mixins has
implementation detail an interface does not know about. But that does not
change the general idea of using mixins.

Mikkel

<snip original mail>

[Walter]: I think mixins are a good idea. Why not post this to the D
newsgroup? There
are some pretty smart people there to comment on it.

----- Original Message -----
From: "Mikkel Fahnøe Jørgensen"
To: <Walter>
Sent: Sunday, December 14, 2003 7:35 AM
Subject: D interfaces, mixins?


D has interfaces where C++ has multiple inheritance. This is generally a
good thing.

In C++ you frequently have a situation where you manually have to re-write
functions of base classes (or delegates) and writing stub calls to base
classes. This is very tedious and error prone.

The use of interfaces in D helps resolve a lot of issues with multiple
inheritance. As far as I can see much like in Java.

It seems to me like in you do not avoid the need to write these forwarding
calls in D, just as in Java.

The Ruby programming language has the same concept of single inheritence,
but introduces mixins (I think it originates from small-talk or similar.

A mixin kind of copy pastes the members of one class into another class
withing the semantic meaning being as if you had written the code manually.

Here is a possible syntax for mixins:

interface IStream { char [] read(); void write(char []); }
class StdReader { char [] read() { ... read and return data; }
class StdWriter { void write(char [] data) {
class MyDataStorage : IStream, mixin StdReader, mixin StdWriter { }

Mixins don't have the same ambiguities as multiple inheritance.
If multiple mixins are included which have overlapping members, it is either
an error, or the definition of the last mixin. If a mixin member conflicts
with a member of the class it is being mixed into, it is an error, or the
member overrides the conflicting mixin definition.

class StdStream { char [] Read() { ... }; void StdWrite(char [] data) {
... } }
class MyStorage : IStream, StdStream { void Write(char []) { ... } }

Mixins would require some more thinking, but I believe this could be a
killer feature of D.

The great thing about mixins and interface vs. multiple inheritance is that
you separate interface from implementation. But interfaces alone does not
easily allow for easy implementations.

A more advanced mixin feature could be to filter a mixin through an
interface such that only those members of a mixins that implements one or
more interface members would be included:

interface IReader { char [] Read(); }
class MyStorage2 : IStream, mixin StdStream for IReader { Write(char[]) {
... } }

It could also be that mixins shouldn't be standard classes but special mixin
types. In Ruby you have classes and modules. You mixin modules, not classes.
The syntax could be:

mixin MReader { char [] Read() { ... } }
interface IReader { char [] Read(); }
class MyReader : IReader, MReader {}

I know that mixins may seem a lot like multiple inheritance. But you cannot
cast to a mixin type. A mixin is just a macro for making it easier to write
a class implementation.


More info on Ruby
www.ruby-lang.org

Regards

Mikkel Fahnøe Jørgensen
Dec 14 2003
next sibling parent reply Patrick Down <pat codemoon.com> writes:
"MikkelFJ" <mikkel dvideNOSPAMDOT.com> wrote in
news:briles$9ku$1 digitaldaemon.com: 

 The Ruby programming language has the same concept of single
 inheritence, but introduces mixins (I think it originates from
 small-talk or similar. 
 
 A mixin kind of copy pastes the members of one class into another
 class withing the semantic meaning being as if you had written the
 code manually. 
I am a big advocate of mixins. Mixins can already be done in D with templates but the syntax is very clumsy. It basically involves inheriting from a chain of template instantiations. The following code segment is an example of this and actaully compiles. template IOTemplate(BASE) { class StdReader : BASE { char[] read() { /*... read and return data;*/ return ""; } } class StdWriter : BASE { void write(char[] data) { /*... write data;*/ } } } class Nothing { } class MyDataStorage : instance IOTemplate( instance IOTemplate(Nothing).StdReader ).StdWriter { } int main(char[][] argv) { MyDataStorage my = new MyDataStorage(); return 0; } Of course you are right that you may want to use mixins with interfaces and does present another inconvenience with the syntax. If change MyDataStorage to use the IOStream interface you will receive a compiler error. interface IOStream { char [] read(); void write(char []); } class MyDataStorage : instance IOTemplate( instance IOTemplate(Nothing).StdReader ).StdWriter, IOStream { } The compler error is: mixin.d: class MyDataStorage interface function IOStream.read is not implemented The reason for this error is that in D a class can't use functions inherited from a base class to fill the slots from the interface definition. All the interface functions must be directly defined in the class that declares the interface. So to fix the compiler error you would have to do this: class MyDataStorage : instance IOTemplate( instance IOTemplate(Nothing).StdReader ).StdWriter, IOStream { char[] read() { return super.read(); } void write(char[] param) { super.write(param); } } I think this solution is terribly inconvenent. There is going to be (hopefully, please, please) another pass at the template implementation in D that will address the general template issues. So this way of doing mixins will hopefully be easier.
Dec 14 2003
parent "Walter" <walter digitalmars.com> writes:
"Patrick Down" <pat codemoon.com> wrote in message
news:Xns9451B74F0618Epatcodemooncom 63.105.9.61...
 There is going to be (hopefully, please, please)
 another pass at the template implementation in D
Yes. <g>
Dec 17 2003
prev sibling next sibling parent reply "Matthew Wilson" <matthew.hat stlsoft.dot.org> writes:
The term "mixin" comes from the bits of biscuits (cookies to the Western
Hemipherians), cakes (buns to the Aussies), scones (or sc"oa"nes for those
on the west side of the Pennines) and cheesecakes, that were added into
ice-cream (glace to the French, gelato to the Italians) to make it
extra-specially yummy. I think it's a western USA term, but I couldn't be
sure.

In terms of programming, the mixin notion you propose is a nice idea, and
one that is certain to be found either automatically (as you propose) or
manually (a la Java) as D grows.

My concern is whether you've (or Ruby's) addressed the issue of name-clash
when multiple mixin-provided interface method names clash. But, AFAIAA, this
is an issue not yet resolved in D irrespective of mixins. Just disallowing
inheritance from two clashing interfaces doesn't seem like much of an answer
to me. This is one way in which multiple inheritance is a must.

Otherwise, I like it. Let's have an experimental go with it in 0.78. :)

Matthew

"MikkelFJ" <mikkel dvideNOSPAMDOT.com> wrote in message
news:briles$9ku$1 digitaldaemon.com...
 Walter asked me to post this on the newsgroup, my original mail below.

 Note to below: Thinking some more about the sugg. about filtering mixins
 through an interface, I think it will not work because mixins may also
need
 to include helper functions on non-public members i.e. mixins has
 implementation detail an interface does not know about. But that does not
 change the general idea of using mixins.

 Mikkel

 <snip original mail>

 [Walter]: I think mixins are a good idea. Why not post this to the D
 newsgroup? There
 are some pretty smart people there to comment on it.

 ----- Original Message -----
 From: "Mikkel Fahnøe Jørgensen"
 To: <Walter>
 Sent: Sunday, December 14, 2003 7:35 AM
 Subject: D interfaces, mixins?


 D has interfaces where C++ has multiple inheritance. This is generally a
 good thing.

 In C++ you frequently have a situation where you manually have to re-write
 functions of base classes (or delegates) and writing stub calls to base
 classes. This is very tedious and error prone.

 The use of interfaces in D helps resolve a lot of issues with multiple
 inheritance. As far as I can see much like in Java.

 It seems to me like in you do not avoid the need to write these forwarding
 calls in D, just as in Java.

 The Ruby programming language has the same concept of single inheritence,
 but introduces mixins (I think it originates from small-talk or similar.

 A mixin kind of copy pastes the members of one class into another class
 withing the semantic meaning being as if you had written the code
manually.
 Here is a possible syntax for mixins:

 interface IStream { char [] read(); void write(char []); }
 class StdReader { char [] read() { ... read and return data; }
 class StdWriter { void write(char [] data) {
 class MyDataStorage : IStream, mixin StdReader, mixin StdWriter { }

 Mixins don't have the same ambiguities as multiple inheritance.
 If multiple mixins are included which have overlapping members, it is
either
 an error, or the definition of the last mixin. If a mixin member conflicts
 with a member of the class it is being mixed into, it is an error, or the
 member overrides the conflicting mixin definition.

 class StdStream { char [] Read() { ... }; void StdWrite(char [] data) {
 ... } }
 class MyStorage : IStream, StdStream { void Write(char []) { ... } }

 Mixins would require some more thinking, but I believe this could be a
 killer feature of D.

 The great thing about mixins and interface vs. multiple inheritance is
that
 you separate interface from implementation. But interfaces alone does not
 easily allow for easy implementations.

 A more advanced mixin feature could be to filter a mixin through an
 interface such that only those members of a mixins that implements one or
 more interface members would be included:

 interface IReader { char [] Read(); }
 class MyStorage2 : IStream, mixin StdStream for IReader { Write(char[]) {
 ... } }

 It could also be that mixins shouldn't be standard classes but special
mixin
 types. In Ruby you have classes and modules. You mixin modules, not
classes.
 The syntax could be:

 mixin MReader { char [] Read() { ... } }
 interface IReader { char [] Read(); }
 class MyReader : IReader, MReader {}

 I know that mixins may seem a lot like multiple inheritance. But you
cannot
 cast to a mixin type. A mixin is just a macro for making it easier to
write
 a class implementation.


 More info on Ruby
 www.ruby-lang.org

 Regards

 Mikkel Fahnøe Jørgensen
Dec 14 2003
next sibling parent reply brad beveridge <brad nospam.com> writes:
How about requiring any name clashed mixins to be explicity referenced 
by their base class.

ie
class A { void doSomething();
	  void somethingA(); }
class B { void doSomething();
  	  void somethingB(); }
class C : mixin A, mixin B
{
};

And be required to call functions as
C.somethingA();
C.somethingB();
C.A.doSomething();
C.B.doSomething();

Brad

Matthew Wilson wrote:
 The term "mixin" comes from the bits of biscuits (cookies to the Western
 Hemipherians), cakes (buns to the Aussies), scones (or sc"oa"nes for those
 on the west side of the Pennines) and cheesecakes, that were added into
 ice-cream (glace to the French, gelato to the Italians) to make it
 extra-specially yummy. I think it's a western USA term, but I couldn't be
 sure.
 
 In terms of programming, the mixin notion you propose is a nice idea, and
 one that is certain to be found either automatically (as you propose) or
 manually (a la Java) as D grows.
 
 My concern is whether you've (or Ruby's) addressed the issue of name-clash
 when multiple mixin-provided interface method names clash. But, AFAIAA, this
 is an issue not yet resolved in D irrespective of mixins. Just disallowing
 inheritance from two clashing interfaces doesn't seem like much of an answer
 to me. This is one way in which multiple inheritance is a must.
 
 Otherwise, I like it. Let's have an experimental go with it in 0.78. :)
 
 Matthew
 
 "MikkelFJ" <mikkel dvideNOSPAMDOT.com> wrote in message
 news:briles$9ku$1 digitaldaemon.com...
 
Walter asked me to post this on the newsgroup, my original mail below.

Note to below: Thinking some more about the sugg. about filtering mixins
through an interface, I think it will not work because mixins may also
need
to include helper functions on non-public members i.e. mixins has
implementation detail an interface does not know about. But that does not
change the general idea of using mixins.

Mikkel

<snip original mail>

[Walter]: I think mixins are a good idea. Why not post this to the D
newsgroup? There
are some pretty smart people there to comment on it.

----- Original Message -----
From: "Mikkel Fahnøe Jørgensen"
To: <Walter>
Sent: Sunday, December 14, 2003 7:35 AM
Subject: D interfaces, mixins?


D has interfaces where C++ has multiple inheritance. This is generally a
good thing.

In C++ you frequently have a situation where you manually have to re-write
functions of base classes (or delegates) and writing stub calls to base
classes. This is very tedious and error prone.

The use of interfaces in D helps resolve a lot of issues with multiple
inheritance. As far as I can see much like in Java.

It seems to me like in you do not avoid the need to write these forwarding
calls in D, just as in Java.

The Ruby programming language has the same concept of single inheritence,
but introduces mixins (I think it originates from small-talk or similar.

A mixin kind of copy pastes the members of one class into another class
withing the semantic meaning being as if you had written the code
manually.
Here is a possible syntax for mixins:

interface IStream { char [] read(); void write(char []); }
class StdReader { char [] read() { ... read and return data; }
class StdWriter { void write(char [] data) {
class MyDataStorage : IStream, mixin StdReader, mixin StdWriter { }

Mixins don't have the same ambiguities as multiple inheritance.
If multiple mixins are included which have overlapping members, it is
either
an error, or the definition of the last mixin. If a mixin member conflicts
with a member of the class it is being mixed into, it is an error, or the
member overrides the conflicting mixin definition.

class StdStream { char [] Read() { ... }; void StdWrite(char [] data) {
... } }
class MyStorage : IStream, StdStream { void Write(char []) { ... } }

Mixins would require some more thinking, but I believe this could be a
killer feature of D.

The great thing about mixins and interface vs. multiple inheritance is
that
you separate interface from implementation. But interfaces alone does not
easily allow for easy implementations.

A more advanced mixin feature could be to filter a mixin through an
interface such that only those members of a mixins that implements one or
more interface members would be included:

interface IReader { char [] Read(); }
class MyStorage2 : IStream, mixin StdStream for IReader { Write(char[]) {
... } }

It could also be that mixins shouldn't be standard classes but special
mixin
types. In Ruby you have classes and modules. You mixin modules, not
classes.
The syntax could be:

mixin MReader { char [] Read() { ... } }
interface IReader { char [] Read(); }
class MyReader : IReader, MReader {}

I know that mixins may seem a lot like multiple inheritance. But you
cannot
cast to a mixin type. A mixin is just a macro for making it easier to
write
a class implementation.


More info on Ruby
www.ruby-lang.org

Regards

Mikkel Fahnøe Jørgensen
Dec 14 2003
next sibling parent Stephan Wienczny <wienczny web.de> writes:
brad beveridge wrote:

 How about requiring any name clashed mixins to be explicity referenced 
 by their base class.
 
 ie
 class A { void doSomething();
       void somethingA(); }
 class B { void doSomething();
        void somethingB(); }
 class C : mixin A, mixin B
 {
 };
 
 And be required to call functions as
 C.somethingA();
 C.somethingB();
 C.A.doSomething();
 C.B.doSomething();
 
 Brad
 
I don't like this style because you have direct calls and something like indirekt calls to methods of mixins. You should have define the behavior if it is not clear. You could make those clashed methods something like abstract methods. Then the compiler would say that there is something wrong... I'm using your example. class C: mixin A, mixin B { void something(){A.somethingA();} } You could use the base mixin versions by downcasting.... Stephan
Dec 15 2003
prev sibling parent "MikkelFJ" <mikkel dvideNOSPAMDOT.com> writes:
 How about requiring any name clashed mixins to be explicity referenced
 by their base class.

 ie
 class A { void doSomething();
   void somethingA(); }
 class B { void doSomething();
     void somethingB(); }
 class C : mixin A, mixin B
 {
 };

 And be required to call functions as
 C.somethingA();
 C.somethingB();
 C.A.doSomething();
 C.B.doSomething();
I don't think this is a particularly good idea because it works against the entire idea that mixins simply implements the class. The above adds some level of scoping to the mixins and you are getting closer to the problems of multiple inheritance. However, the related problem of clashing interface members could perhaps be resolved this way: (disclaimer - I'm not that deep into the semantics of D to know if this is already covered somehow) interface IA { void foo(); } interface IB { void foo(); } class X : IA, IB { IA.foo() { ... }; IB foo() { ... } } This could be extended to mixins: class A { IA.foo() { ... } } // can't be instantiated due to lack of interface, but can be mixed in class B { IB.foo() {...} } // ditto class X : IA, IB, A, B {} This leverages the idea that interfaces define the interface and mixins are just helpers. Sometimes we want one method to implement clashing names in interfaces: For example an array interface and a list interface. A class could expose both interfaces and both interfaces have a "int size();" method: interface IVector { int size(); ... } interface IList { int size(); ... } class Collection : IVector, IList { int _size; int size() { return size(); } ... } Here size maps to both interfaces. The problem is that all this semantic rules makes it difficult to understand and remember and thus again approaching the complexity of C++ multiple inheritance. Mikkel
Dec 15 2003
prev sibling next sibling parent Luke D <Luke_member pathlink.com> writes:
Which reminds me, I don't think the name-clash problem with multiple interfaces
with the same methods that are meant to have different uses was every addressed.


problem.

In article <brit5d$kh5$1 digitaldaemon.com>, Matthew Wilson says...
The term "mixin" comes from the bits of biscuits (cookies to the Western
Hemipherians), cakes (buns to the Aussies), scones (or sc"oa"nes for those
on the west side of the Pennines) and cheesecakes, that were added into
ice-cream (glace to the French, gelato to the Italians) to make it
extra-specially yummy. I think it's a western USA term, but I couldn't be
sure.

In terms of programming, the mixin notion you propose is a nice idea, and
one that is certain to be found either automatically (as you propose) or
manually (a la Java) as D grows.

My concern is whether you've (or Ruby's) addressed the issue of name-clash
when multiple mixin-provided interface method names clash. But, AFAIAA, this
is an issue not yet resolved in D irrespective of mixins. Just disallowing
inheritance from two clashing interfaces doesn't seem like much of an answer
to me. This is one way in which multiple inheritance is a must.

Otherwise, I like it. Let's have an experimental go with it in 0.78. :)

Matthew
Dec 15 2003
prev sibling parent "MikkelFJ" <mikkel dvideNOSPAMDOT.com> writes:
"Matthew Wilson" <matthew.hat stlsoft.dot.org> skrev i en meddelelse
news:brit5d$kh5$1 digitaldaemon.com...

 My concern is whether you've (or Ruby's) addressed the issue of name-clash
 when multiple mixin-provided interface method names clash. But, AFAIAA,
this I'm sure there are a number of stones to be turned before mixins can be considered to be a practical concept. I intentionally left the issue of clashing mixins open by suggesting either an error or that the last mixin definition wins. (I did not originally address interface member clashes). Clashes in Ruby mixins are resolved by letting the last definition win. This is due to the dynamic nature of Ruby because you can always redefine a method in Ruby (save frozen classes). This may or may not be a suitable behavior of a somewhat strongely typed language like D. It's mostly a matter of philosophy. I would find redefinition useful, but I also think D is close enough to C++ for users to expect an error in case of clashes. Also refer to my other posting about the option to prefix methods with interface names answering Brad Beveridge.
 is an issue not yet resolved in D irrespective of mixins. Just disallowing
 inheritance from two clashing interfaces doesn't seem like much of an
answer
 to me. This is one way in which multiple inheritance is a must.
This was also a source of inspiration for my other posting concerned with interface prefixes. Mikkel
Dec 15 2003
prev sibling next sibling parent reply "Y.Tomino" <demoonlit inter7.jp> writes:
(I'm glad! :-)

I suggest "interface delegation" like Delphi.
It fits to "COM"(Component-Object-Model) well,
and necessary to "aggregation" of COM.

//sample (Delphi)
type
  MyClass = class(ParentClass, InterfaceA)
  private
    ARef: TheClassImplementsInterfaceA;
  public
    property A: TheClassImplementsInterfaceA read ARef implements
InterfaceA;
  end;

//D?
class MyClass : ParentClass, InterfaceA
{
  private TheClassImplementsInterfaceA aRef;
  TheClassImplementsInterfaceA a() implements InterfaceA { return aRef; }
//property
}

MyClass can override some methods of InterfaceA,
and remaining methods dispatched to "aRef".
We can exchange aRef at run-time. It's a little advantage.

Another advantage is that "interface delegation" don't require special
definition
like "mixin MReader { char [] Read() { ... } }".
"Interface delegation" is able to use the existing class.

(if you can read Japanease, please read a shinichiro.h's analysis.
 "Method delegation" like "Uva" interests me, too.
 http://d.hatena.ne.jp/shinichiro_h/20031213#p1)

Thanks.
YT
Dec 14 2003
next sibling parent Patrick Down <pat codemoon.com> writes:
I like this idea.

"Y.Tomino" <demoonlit inter7.jp> wrote in
news:brj1ui$r60$1 digitaldaemon.com: 

 (I'm glad! :-)
 
 I suggest "interface delegation" like Delphi.
 It fits to "COM"(Component-Object-Model) well,
 and necessary to "aggregation" of COM.
 
 //sample (Delphi)
 type
   MyClass = class(ParentClass, InterfaceA)
   private
     ARef: TheClassImplementsInterfaceA;
   public
     property A: TheClassImplementsInterfaceA read ARef implements
 InterfaceA;
   end;
 
 //D?
 class MyClass : ParentClass, InterfaceA
 {
   private TheClassImplementsInterfaceA aRef;
   TheClassImplementsInterfaceA a() implements InterfaceA { return
   aRef; } 
 //property
 }
 
 MyClass can override some methods of InterfaceA,
 and remaining methods dispatched to "aRef".
 We can exchange aRef at run-time. It's a little advantage.
 
 Another advantage is that "interface delegation" don't require special
 definition
 like "mixin MReader { char [] Read() { ... } }".
 "Interface delegation" is able to use the existing class.
 
 (if you can read Japanease, please read a shinichiro.h's analysis.
  "Method delegation" like "Uva" interests me, too.
  http://d.hatena.ne.jp/shinichiro_h/20031213#p1)
 
 Thanks.
 YT
 
 
Dec 14 2003
prev sibling parent "MikkelFJ" <mikkel dvideNOSPAMDOT.com> writes:
"Y.Tomino" <demoonlit inter7.jp> skrev i en meddelelse
news:brj1ui$r60$1 digitaldaemon.com...
 (I'm glad! :-)

 I suggest "interface delegation" like Delphi.
...
     property A: TheClassImplementsInterfaceA read ARef implements
This is a nice concept. I do not think it entirely replaces the concept of mixins but it certainly does solve a number of issues. There are also performance issues - mixins are not only useful for late binding interface implementation. Also mixins decouples "who implements what" from the interface. In any case this is a nice idea. If the delegate concept is implemented, one might argue that mixins will not add enough benefits to warrant the added complexity of the language ... but then again it could be useful in its own right :-) BTW, Ruby also has a concept of delegates - but this is implemented on top of the language thanks to reflection and the highly dynamic nature of this language. As far as I am aware delegates are not used nearly as often as mixins in Ruby, but then again Ruby doesn't really have the same concept (or need for) of interfaces. One example of mixins in Ruby: An array module is mixed into a number of classes offering collections. Another mixin could then be created to piggy-backs on array methods by supplying a sort method working on the standard array methods. Note that there isn't really an array interface, just a convention of what methods an array has. (This is known as Duck typing: If it quacks like a duck, it is a duck.). This is a way to use mixins without using interfaces. Contrary to Ruby, D is statically typed. This means the compiler would discover errors Ruby would only discover in runtime. Yet mixins adds a rather informal dynamic nature to class design while avoiding some of the potential runtime errors seen in Ruby. There are links from here to the concepts of algorithms in C++ STL. You can have algorithms mixed in. Mixins could probably be templated as well. class DiskRecordSet { T get(int index) { ... }; void set(T value) { ... }; int size() { ...} } class MemArray { T get(int index) { ... }; void set(T value) { ... }; int size() { ...} } class QuickSorter { void sort() { ... impl. quick sort using get, set, size methods } } class MergeSorter { void sort() { ... impl. merge sort using get, set, size methods } } class Filer : mixin DiskRecordSet, mixin MergeSorter {} class WorkingSet : mixin MemArray, mixin MergeSorter {} These operations do not work in interfaces but rather on conventions. This makes it easy to create efficient implementations with relying heavily on specific class types which would require templates that is often more tedious to work with. At the same time mixins are so much convention that it is useful to combine them with interfaces at the inter-module level. Thus we could combine the above storage implementations with stream interfaces as shown earlier.
 Another advantage is that "interface delegation" don't require special
 definition
 like "mixin MReader { char [] Read() { ... } }".
 "Interface delegation" is able to use the existing class.
Hmm not necessarily. The mixin definition was just a suggestion. My proposal also considers the alternative of allowing ordinary classes to be mixed in: class Reader { char [] Read() {...} } class Storage : mixin Reader { .... } Mikkel
Dec 15 2003
prev sibling parent reply Benji Smith <dlanguage xxagg.com> writes:
The only possible problem that crosses my mind is that mixins will need some
mechanism to access the data members of the classes that import them. There will
also need to be a safety mechanism to keep mixins from modifying class data that
they shouldn't be touching.

It's late at night, though, and I can't think of any example syntax that
illustrates what I'm talking about.

--Benji
Dec 15 2003
parent reply "Matthew Wilson" <matthew.hat stlsoft.dot.org> writes:
You should write a book!

12-months of brain freeze. ;(


"Benji Smith" <dlanguage xxagg.com> wrote in message
news:brm8ue$2mb0$1 digitaldaemon.com...
 The only possible problem that crosses my mind is that mixins will need
some
 mechanism to access the data members of the classes that import them.
There will
 also need to be a safety mechanism to keep mixins from modifying class
data that
 they shouldn't be touching.

 It's late at night, though, and I can't think of any example syntax that
 illustrates what I'm talking about.

 --Benji
Dec 15 2003
parent Benji Smith <dlanguage xxagg.com> writes:
On Tue, 16 Dec 2003 17:47:03 +1100, "Matthew Wilson"
<matthew.hat stlsoft.dot.org> wrote:

You should write a book!

12-months of brain freeze. ;(
Ouch.
Dec 16 2003