On Mon, 24 Feb 2014 16:24:00 -0500, Frustrated <c1514...@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 <c1514...@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