D - Mixins
- Patrick Down (33/33) Oct 18 2002 As I was doing my day job today, writing C++ code
- Sean L. Palmer (61/94) Oct 19 2002 Yes. Wow. That's alot like the C++ trick of inheriting from a template
- Patrick Down (23/64) Oct 19 2002 Yes.
- Sean L. Palmer (5/69) Oct 19 2002 So you're advocating generics as being a suitable replacement for MI?
- Paul Conway (25/25) Jan 19 2003 Some thoughts about mixins based on my experience with the Smallworld Ma...
As I was doing my day job today, writing C++ code and wishing it was D, I found myself once again wanting a feature that neither C++ nor D has. What I want are mixins. You will find various explanations of mixins on the web but to me they are just aggregation with a twist. The twist is that aggregated object has some access to the object in which it is aggregated into. I think that with D's templates could be extended to cover this feature. My suggested syntax for this would be. template Mixin(this) { int foo; int AccessAggObj(int a) { return this.ParentFunc() + foo + a; } } class UseMixin { int ParentFunc() { return 12; } instance Mixin(this) bar; // foo and AccessAggObj are // made members of the class // accessible from bar; } UseMixin a = new UseMixin(); a.bar.foo = 5; a.bar.AccessAggObj(7); // returns 24
Oct 18 2002
Yes. Wow. That's alot like the C++ trick of inheriting from a template that is parameterized with the derived class: template <class Derived> class Wierd { public: int Foo(int a) { return Derived::Bar(a+1)+4; } }; class Wierder : public Wierd<Wierder> { public: void Test() { std::cout << Foo(3); // prints 5 } int Bar(int b) { return b + 2; } }; Voila! Method overriding without vtables. No virtual function table necessary. Call functions that only exist in your derived classes. Why do you need abstract functions? Just call a function on the derived class and let the compiler try to figure it out. If it can't it's an error. It's a cool trick. It could certainly use prettier syntax. But your thing looks like it could be better possibly. I would want mixins even if it's just inheriting a partial implementation for an interface that is declared somewhere else. I like interfaces. But oftentimes you want to provide some default implementation. That's why I like multiple inheritance and mixins. Otherwise you have to duplicate alot of interfaces (by hand, or cut and paste) to accomplish the same thing. Maybe it's more like an inherited "feature" that I want. Exposing this packaged feature that you get from somewhere else. Maybe what I want is to be able to have a class "merge" another class into itself. class A { int feature1; } class B { int feature2; mixin A; } void Test() { B b; printf(b.feature2); // ok printf(b.feature1); // ok also } Need some way to deal with name conflicts. But this is almost essentially Multiple Inheritance. I could handle it if all conflicts were resolved with that all of the conflicting declarations has to be abstract (the interface) and only one must be an implementation. MI so long as you promise the compiler there will be no collisions. If there are collisions you have to rename something. So it'd be mainly good for use inside a single component where you can control use of it. Not something you want to expose to the outside world. Sean "Patrick Down" <pat codemoon.com> wrote in message news:Xns92ABA418CB124patcodemooncom 63.105.9.61...As I was doing my day job today, writing C++ code and wishing it was D, I found myself once again wanting a feature that neither C++ nor D has. What I want are mixins. You will find various explanations of mixins on the web but to me they are just aggregation with a twist. The twist is that aggregated object has some access to the object in which it is aggregated into. I think that with D's templates could be extended to cover this feature. My suggested syntax for this would be. template Mixin(this) { int foo; int AccessAggObj(int a) { return this.ParentFunc() + foo + a; } } class UseMixin { int ParentFunc() { return 12; } instance Mixin(this) bar; // foo and AccessAggObj are // made members of the class // accessible from bar; } UseMixin a = new UseMixin(); a.bar.foo = 5; a.bar.AccessAggObj(7); // returns 24
Oct 19 2002
"Sean L. Palmer" <seanpalmer directvinternet.com> wrote in news:aor45k$12of$1 digitaldaemon.com:Yes. Wow. That's alot like the C++ trick of inheriting from a template that is parameterized with the derived class:Yes.It's a cool trick. It could certainly use prettier syntax. But your thing looks like it could be better possibly. I would want mixins even if it's just inheriting a partial implementation for an interface that is declared somewhere else. I like interfaces. But oftentimes you want to provide some default implementation. That's why I like multiple inheritance and mixins. Otherwise you have to duplicate alot of interfaces (by hand, or cut and paste) to accomplish the same thing.OOP pays a lot of attention to the "is-a" type relations. It's all about creating abstract interfaces that allow specific objects to be dealt with in a uniform manner. I think perhaps there could be some advances made in dealing with "has-a" type relationships. I'm creating a car object. It has an engine, wheels, body, transmission, etc... I aggregate all these things into the car object and then I spend time wiring together the various inputs and output of the components to each other and the external car interfaces. Why can't there be some help with the wiring process? Why can't an engine expect that it's container implements some sort of throttle control? I see this as another sort of contract in a way. To use an engine you must implement the correct set of inputs and output for it. Anyway I see mixins as sort of a step in this direction.Maybe it's more like an inherited "feature" that I want. Exposing this packaged feature that you get from somewhere else. Maybe what I want is to be able to have a class "merge" another class into itself. class A { int feature1; } class B { int feature2; mixin A; } void Test() { B b; printf(b.feature2); // ok printf(b.feature1); // ok also } Need some way to deal with name conflicts. But this is almost essentially Multiple Inheritance. I could handle it if all conflicts were resolved with that all of the conflicting declarations has to be abstract (the interface) and only one must be an implementation. MI so long as you promise the compiler there will be no collisions. If there are collisions you have to rename something. So it'd be mainly good for use inside a single component where you can control use of it. Not something you want to expose to the outside world.With D, doing mixins with templates does away with the naming conflicts and with all the associated problems with MI. The naming conflicts go away because the D templates require a instance identifier. The MI issues go away because code is not generated until the template is instanced in the class.
Oct 19 2002
So you're advocating generics as being a suitable replacement for MI? Mayhap... must think about it. Sean "Patrick Down" <pat codemoon.com> wrote in message news:Xns92AC99CCA95D8patcodemooncom 63.105.9.61..."Sean L. Palmer" <seanpalmer directvinternet.com> wrote in news:aor45k$12of$1 digitaldaemon.com:Yes. Wow. That's alot like the C++ trick of inheriting from a template that is parameterized with the derived class:Yes.It's a cool trick. It could certainly use prettier syntax. But your thing looks like it could be better possibly. I would want mixins even if it's just inheriting a partial implementation for an interface that is declared somewhere else. I like interfaces. But oftentimes you want to provide some default implementation. That's why I like multiple inheritance and mixins. Otherwise you have to duplicate alot of interfaces (by hand, or cut and paste) to accomplish the same thing.OOP pays a lot of attention to the "is-a" type relations. It's all about creating abstract interfaces that allow specific objects to be dealt with in a uniform manner. I think perhaps there could be some advances made in dealing with "has-a" type relationships. I'm creating a car object. It has an engine, wheels, body, transmission, etc... I aggregate all these things into the car object and then I spend time wiring together the various inputs and output of the components to each other and the external car interfaces. Why can't there be some help with the wiring process? Why can't an engine expect that it's container implements some sort of throttle control? I see this as another sort of contract in a way. To use an engine you must implement the correct set of inputs and output for it. Anyway I see mixins as sort of a step in this direction.Maybe it's more like an inherited "feature" that I want. Exposing this packaged feature that you get from somewhere else. Maybe what I want is to be able to have a class "merge" another class into itself. class A { int feature1; } class B { int feature2; mixin A; } void Test() { B b; printf(b.feature2); // ok printf(b.feature1); // ok also } Need some way to deal with name conflicts. But this is almost essentially Multiple Inheritance. I could handle it if all conflicts were resolved with that all of the conflicting declarations has to be abstract (the interface) and only one must be an implementation. MI so long as you promise the compiler there will be no collisions. If there are collisions you have to rename something. So it'd be mainly good for use inside a single component where you can control use of it. Not something you want to expose to the outside world.With D, doing mixins with templates does away with the naming conflicts and with all the associated problems with MI. The naming conflicts go away because the D templates require a instance identifier. The MI issues go away because code is not generated until the template is instanced in the class.
Oct 19 2002
Some thoughts about mixins based on my experience with the Smallworld Magik language: Magik uses mixins as a major and very powerful feature. However it can lead to a form of confusion that is best avoided. That is, a programmer devising a new class looks thru a list of mixins and picks a few he thinks he needs, overrides the functions he does not like, and adds what is missing. He now has a class that without the mixins would have taken him a lot longer to write. However the possibilities for laziness abound. If a class needs some functionality added, just add a mixin; and this can go on and on. Adding is easy. Pruning out what is not needed is the hard part. Mixins tend to provide everything including the kitchen sink, ie far more than is required in many cases, simply because they were written, with the best intentions, for maximum flexibility and usefulness. And all those functions you don't use are sitting there waiting to confuse a maintenance programmer because he may not have a clue as to which ones are surplus to requirements. Ones that ought never to be called are still available. He cannot therefore just pull out a few mixins that don't look important. He might cause unexpected problems at run-time (which is when the linkages to mixin functions get automatically cached on-demand, in Magik). In D, the same problem would occur at compile-time. Magik allows multiple-inheritance. Though it is easy enough to do, out of thousands of object classes, a mere handful have ever used it, and could be rewritten to not do so. The availability of mixins made the use of multiple-inheritance effectively unnecessary and, if this had been known when the code base development began, the multiple-inheritance feature might well have been removed from the compiler.
Jan 19 2003