Multiple subtyping with alias this and nested classes

Max Samukha spambox at d-coding.com
Sun Oct 4 05:26:53 PDT 2009


On Sun, 04 Oct 2009 06:31:25 -0400, Yigal Chripun <yigal100 at gmail.com>
wrote:

>Max Samukha Wrote:
>
>> On Sun, 04 Oct 2009 00:10:30 +0200, Yigal Chripun <yigal100 at gmail.com>
>> wrote:
>> 
>> >
>> >class FlippingBlipper : IBlipper, IFilpper
>> >{
>> >     mixin Flipper F;
>> >     mixin Blipper B;
>> >     alias F.nameCollision nameCollision;
>> >}
>> >
>> 
>> The problem is that IBlipper.nameCollision is totally unrelated 
>> to IFlipper.nameCollision (for example, if the interfaces/mixins come
>> from third-party libraries, whose developers don't know or care
>> about each other, e.g. Tango/Phobos :P). That's why either
>> nameCollision must have its own implementation.
>> 
>> In current D:
>> 
>> auto fb = new FlippingBlipper;
>> IFlipper f = fb;
>> IBlipper b = fb;
>> f.nameCollision;
>> b.nameCollision;
>> 
>> Both calls are dispatched to the same implementation (the one provided
>> by Flipper template), which is incorrect and undesirable.
>> 
>> >I wonder if the following would work:
>> >
>> >class FlippingBlipper : IBlipper, IFilpper
>> >{
>> >     mixin Flipper IFilpper;
>> >     mixin Blipper IBlipper;
>> >}
>> >
>> >
>> 
>> I don't think so.
>
>I see. What you want is non-virtual MI. 
>I don't think that allowing the derived class to have two distinct implementations for the same function prototype is a good idea. 
>Eiffel handles this by giving the programmer controls to select features and rename them in the derived class which I think is better. 
>
>// hypothetical syntax example
>class FlippingBlipper : IBlipper, IFilpper {
>     mixin Flipper F;
>     mixin Blipper B;
>     // rename the inherited interface functions 
>     alias IBlipper.nameCollision boo;
>     alias IFilpper.nameCollision foo;
>    // implement the now two distinct functions
>   void foo() { F.nameCollision(); }
>   void boo() { B.nameCollision(); }
>}
>
>you can further subtype and the derived foo & boo will override the respective interfaces. 

Yes, but what if nameCollision is a virtual function called somewhere
in the template mixin? Your example has effectively removed the
virtuality.

If your mixin template contains unimplemented or partially implemented
virtual functions (for example, in case of an abstract base type), you
have to derive another class to (re)implement them.

Ok, I'm not arguing that mixins+interfaces cannot be used to emulate
multiple subtyping. I'm arguing it has problems that may force one to
resort to horrible hacks.

How is it better than the solution provided by 'alias this' and nested
classes? 'alias this' doesn't require mixin templates, handles name
conflicts nicely, allows subtyping of value types, allows
(re)implementing base functions directly in the subtype (using nested
classes). 

BTW, your example rewriten with 'alias this' looks cleaner, IMHO:

class Flipper { ... }
class Blipper { ... }

class FlippingBlipper {
     Flipper flipper;
     Blipper blipper;
     
     this { blipper = new Blipper; flipper = new Flipper; }

     alias this flipper;
     alias this blipper;

     void foo() { blipper.nameCollision; } 
     void bar() { flipper.nameCollision; }
}

No interfaces, no templates, no renaming. Problem solved. Almost. We
have to be able to instantiate classes in-place to avoid unnecessary
allocations.



More information about the Digitalmars-d mailing list