April 22, 2004 Re: Mixin ? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Warren | Ruby (and, I hope, D): 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. C++: A mixin class is a non-primary base class, which generally provides only types and static & non-virtual methods. (If it contains fields / virtual methods, it's a fully fledged base class, IMO) "Warren" <warrens@seanet.com> wrote in message news:c647qp$11vo$1@digitaldaemon.com... What's a mixin? I presume fred meant to ask "Are mixins planned..." "fred" <info@fleet-manage.com> wrote in message news:c625pc$6np$1@digitaldaemon.com... > Is Mixins planned for the version 1.0 release ? |
April 23, 2004 Re: Mixin ? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Matthew | Apologies if some of this seems bleeding obvious, but I hope it may add to the discussion. From what I was taught, there are two primary types of relationships in OOP: "is-a" and "has-a" or Inheritance and Aggregation. // Inheritance Example class Parent { public: Parent() {} void DoSomething() {/* does something */} } class Child : public Parent { public: Child() : Parent() {} void DoSomethingElse() {/* does something else */} } void main() { Child child; child.DoSomething(); // call to parent's method child.DoSomethingElse(); // call to child's method } // Aggregation Example class Body { public: Body() {} }; class Switch { public: Switch() { bState = false; } void Toggle() { !bState; } bool State() { return bState; } private: bool bState; }; class Globe { public: Globe() { bState = false; } void Illuminate( bool state ) { bState = state; } bool IsOn() { return bState; } private: bool bState; } class PowerCord { public: PowerCord() {} }; // Parent class class Light { public: Light() {} }; class Lamp : public Light { public: Lamp() : Light(), cBody(), cSwitch(), cGlobe(), cPowerCord {} void Toggle( bool state ) { cSwitch.Toggle( state ); } bool State() { return cSwitch.State(); } void Illuminate( bool state ) { cGlobe.Illuminate( state ); } bool IsOn() { return cGlobe.IsOn(); } private: Body cBody; Switch cSwitch; Globe cGlobe; PowerCord cPowerCord; } void main() { Light lamp = new Lamp(); if( DarkOutside() && !lamp.IsOn()) { // require User Input here lamp.Toggle() lamp.Illuminate( lamp.State()) } } Unfortuantely, the C++ language only supports the former (Inheritance) through the ":" operator, whereas the later (Aggregation) does not have the same syntatical support. As such, many programmers (wrongly, to the purists) use the Inheritance mechanism to perform Aggregation operations, since it saves on coding through not having to redirect methos of subordinate components. For Example; the following produces the same outcome on the earlier main() program. class Lamp : public Light, public Body, public Switch, public Globe, public PowerCord { public: Lamp() : Light(), Body(), Switch(), Globe(), PowerCord {} } This is where I think Mixins can add a great deal of value. For example; class Lamp : public Light, mixin Body cBody, mixin Switch cSwitch, mixin Globe cGlobe, mixin PowerCord cPowerCord { public: Lamp() : Light(), cBody(), cSwitch(), cGlobe(), cPowerCord {} } This is about as lightweight as using multiple inheritance equivilant, and has the same advantage of not having to redefine all the methods from aggregated components. I haven't thought this solution through properly, so excuse me if it appears somewhat haphazard. Comments ??? "Matthew" <matthew.hat@stlsoft.dot.org> wrote in message news:c678mi$4mt$1@digitaldaemon.com... > Ruby (and, I hope, D): 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. > > C++: A mixin class is a non-primary base class, which generally provides only types and static & non-virtual methods. (If it contains fields / virtual methods, it's a fully fledged base class, IMO) > |
April 23, 2004 Re: Mixin ? | ||||
---|---|---|---|---|
| ||||
Posted in reply to fred | In article <c6ae9f$2cfh$1@digitaldaemon.com>, fred says... > >Apologies if some of this seems bleeding obvious, but I hope it may add to the >discussion. Good discussion is always welcome. See comments below. >Unfortuantely, the C++ language only supports the former (Inheritance) through the ":" >operator, whereas the later (Aggregation) does not have the same syntatical support. >As such, many programmers (wrongly, to the purists) use the Inheritance mechanism >to perform Aggregation operations, since it saves on coding through not having to >redirect methos of subordinate components. >For Example; the following produces the same outcome on the earlier main() program. > >class Lamp : public Light, > public Body, > public Switch, > public Globe, > public PowerCord >{ >public: > Lamp() : Light(), Body(), Switch(), Globe(), PowerCord {} >} > > >This is where I think Mixins can add a great deal of value. For example; > >class Lamp : public Light, > mixin Body cBody, > mixin Switch cSwitch, > mixin Globe cGlobe, > mixin PowerCord cPowerCord >{ >public: > > Lamp() : Light(), cBody(), cSwitch(), cGlobe(), cPowerCord {} >} > >This is about as lightweight as using multiple inheritance equivilant, and has the same advantage of not having to redefine all the methods from aggregated components. > >I haven't thought this solution through properly, so excuse me if it appears somewhat haphazard. > >Comments ??? Fred, I agree 100% with you about aggregation not having the same versatility as inheritance. In fact I tend to think that inheritance tends to make programmers think in term of hierarchies where they are not necessarily appropriate. For example: Vehicle -Car --Sports car --Station Wagon -Truck While this hierarchy might be appropriate for organizational purposes you don't build a sports car by modifying some abstract concept of a Vehicle you build it by putting together specific types of components. Sports Car: implements a Vehicle interface and is made up of high performance engine, sleek frame, two seats, manual transmission Station Wagon: implements a Vehicle interface and is made up of ordinary engine, long frame, two bench seats, cargo space, automatic transmission, wood paneling etc... When I think about building software I tend to think less in terms of hierarchies and more in terms of interfaces and building blocks. The thing about build blocks is that you usually have ways of connecting them together. Right now for C++ and D this is a rather manual process. You aggregate all your building blocks into a class and then add functions to the class to expose the functions of the building blocks outside of the class and to wire together various functions of the building blocks to each other. With your mixin example to have hit on the one problem of exposing the functions of the building blocks outside of the class. I'd like to address wiring together various functions of the building blocks to each other Let take your example and go a little farther with it. I'm playing with some syntax here: interface PowerSource { void DrawPower(bool); } interface PowerSink { void UsePower(bool); } class Switch(source : PowerSource, sink : PowerSink) { public: Switch() { bState = false; } void Toggle() { bState = !bState; source.DrawPower(bState); sink.UsePower(bState);} bool State() { return bState; } private: bool bState; }; class PowerCord : PowerSource { public: PowerCord() {} void DrawPower(bool); }; class Globe : PowerSink { public: Globe() { bState = false; } void Illuminate( bool state ) { bState = state; } bool IsOn() { return bState; } void UsePower(bool bState) { Illuminate(bState); } private: bool bState; } class Lamp : public Light { public: Lamp() {} private: mixin Body cBody; mixin Switch cSwitch(cPowerCord,cGlobe); mixin Globe cGlobe; mixin PowerCord cPowerCord; } Thus Switch becomes a mixin that can control anything with the correct interface |
April 24, 2004 Re: Mixin ? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Patrick Down Attachments:
| "Patrick Down" <Patrick_member@pathlink.com> wrote in message news:c6bg2p$146t$1@digitaldaemon.com... Good expansion of the code Patrick, as it shows how process can flow though the aggregated objects, however, there is one thing I would like to comment on. > > > >class Lamp : public Light, > > mixin Body cBody, > > mixin Switch cSwitch, > > mixin Globe cGlobe, > > mixin PowerCord cPowerCord > >{ > >public: > > Lamp() : Light(), cBody(), cSwitch(cPowerCord,cGlobe), cGlobe(), cPowerCord() {} > >} > > Versus > class Lamp : public Light { > public: > Lamp() {} > > private: > mixin Body cBody; > mixin Switch cSwitch(cPowerCord,cGlobe); > mixin Globe cGlobe; > mixin PowerCord cPowerCord; > } Originally, I too had the your later syntax, but changed it the the former for the reasons; 1. Most object diagrams show aggregated objects as external objects, not internal. For example; 2. In your example, you have placed (correctly may I say) the aggreagated objects as private. However, the code is accessing methods of these objects as though they were public. By placing the object declarations outside of the class, they can assume their original access status. 3. As there will be many C++ programs that have been using MI for aggregation techniques, it would be easier to port these to D if their syntax was to remain similiar in structure. I myself fit firmly in the the last categor. There is slabs and slabs of C++ code that I would like to correct the invalid use of Multiple Inheritance to perform Agregation operations. Criticism/Comments ? |
Copyright © 1999-2021 by the D Language Foundation