Programming to Interfaces simplification
Steven Schveighoffer
schveiguy at yahoo.com
Mon Feb 24 14:07:46 PST 2014
On Mon, 24 Feb 2014 16:24:00 -0500, Frustrated <c1514843 at drdrb.com> wrote:
> On Monday, 24 February 2014 at 18:59:32 UTC, Steven Schveighoffer
> wrote:
>> On Mon, 24 Feb 2014 11:36:50 -0500, Frustrated <c1514843 at drdrb.com>
>> wrote:
>>
>>> http://dpaste.dzfl.pl/c25655e2dfe9
>>>
>>> The code above simplifies using interfaces as the programming
>>> object. It allows one to program the derived classes as if they
>>> were not part of an abstraction by mapping the abstracted virtual
>>> methods to concrete methods.
>>>
>>> e.g.,
>>>
>>> class WindowsGui : iGui
>>> {
>>> WindowsButton _button;
>>> @property WindowsButton button(WindowsButton b) { return
>>> (_button = b); }
>>>
>>> mixin(Fixup!(WindowsGui, iButton, WindowsButton));
>>> }
>>>
>>> instead of
>>>
>>> class WindowsGui : iGui
>>> {
>>> WindowsButton _button;
>>> @property iButton button(iButton b)
>>> {
>>> assert(cast(WindowsButton)b !is null, `Invalid object
>>> type dependency mismatch! Type: `~b.classinfo.name~` Type
>>> Expected: WindowsButton`);
>>> auto bb = cast(WindowsButton)b;
>>> // do work with bb.
>>> }
>>> }
>>
>> Nice work!
>>
>>> One problem with the template is that b.classinfo.name returns
>>> the interface instead of the actual class.
>>
>> Hm... classinfo (now typeid) should get the most derived type from an
>> instance. This may be a factor of it being an interface instance vs. a
>> class instance. A simple test:
>>
>> Stevens-MacBook-Pro:~ steves$ cat testinterface.d
>> import std.stdio;
>>
>> interface I
>> {
>> }
>>
>> class C : I
>> {
>> }
>>
>> void main()
>> {
>> I i = new C;
>> writeln(typeid(i).name);
>> writeln(typeid(cast(Object)i).name);
>> }
>> Stevens-MacBook-Pro:~ steves$ ./testinterface
>> testinterface.I
>> testinterface.C
>>
>> Looks like that is the case. Note that classinfo is not part of the
>> language any more, and will likely be deprecated. typeid is the correct
>> mechanism to get the TypeInfo of a derived class.
>>
>> I'm thinking this is incorrect, typeid should get the derived class
>> type IMO. It shouldn't be that difficult or costly for the compiler to
>> do.
>>
>
> Thanks. Now the correct type is known. One could, for example, look for
> wrappers/adapters/etc to get a linuxbutton into a windowsbutton(if so
> desired, throw a well informed error, etc.
>
> Hopefully though, now you see the point. It is a runtime contract
> that you make since you can't specify it at compile time(since D
> doesn't supports it).
Always have seen the point, it is why I suggested this solution.
> Unfortunately the main downside is the vtable is twice as big. Final or
> static methods could be used for this. If the compiler could manage such
> a system it could do the job better. (There would be no extra functions
> needed and the calls would be faster)
First, the vtable is not per-instance, so it doesn't detract too much from
the solution.
Second, the concrete function does not need to be virtual, make it final,
and it won't add to the vtable.
> The issue is this: I want to program to interfaces(requiring the
> class(WindowsGui) to use base interfaces(iButton) to satisfy the
> interface.
>
> The problem is this compile time contract is to generic and makes coding
> the classes more verbose. The mixin reduces the verbosity and provides a
> runtime contract(we enforce it using asserts in this case).
>
> The benefit of the mixin is that coding WindowsGui is simpler and more
> direct and it's dependency on WindowsButton(not iButton) is known at
> compile time(But enforced at runtime by assert). Would you not agree?
> Everything else is essentially identical.
I have written such libraries before (I had an OS abstraction library in
C++), it's not always pretty.
-Steve
More information about the Digitalmars-d-learn
mailing list