Programming to Interfaces simplification

2014-02-24 Thread Frustrated

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.
 }
}

(note the check and the cast are required for all usages of
iButton if one wants to treat it as a WindowsButton. By using the
mix, no checks and no casts are required. Much cleaner looking
and less verbose code results, which is the whole point.)

One problem with the template is that b.classinfo.name returns
the interface instead of the actual class.

In the example on dpaste, b.classinfo.name returns iButton, the
base interface of LinuxButton. I want to display the actual class
name that causes the problem(LinuxButton trying to be used where
a WindowsButton goes).

Obviously the Fixup template is not robust nor optimized for all
cases but should handle most.


Re: Programming to Interfaces simplification

2014-02-24 Thread Steven Schveighoffer

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.


-Steve


Re: Programming to Interfaces simplification

2014-02-24 Thread Frustrated

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).

In any case the mixin needs some work and testing. Would just
like to get the proper class name for the type. It is, at the
very least, a proof of concept.

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)





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.


Re: Programming to Interfaces simplification

2014-02-24 Thread Frustrated

Fixed code with all combination examples:
(again, only WindowsButton works with WindowsGui and same for
LinuxGui... but the classes don't use iButton like they should!!!
Oh, they break the contract!! End of the world!)


http://dpaste.dzfl.pl/02ee45225303

Output:

Trying WindowsButton with WindowsGui!
Do(): WindowsButton
WindowsButton.foo(): I'm an extra WindowsButton feature!
...WindowsButton works in WindowsGui!

Trying LinuxButton with WindowsGui!
Invalid object type dependency mismatch! Type: f324.LinuxButton
Type Expected: WindowsButton


Trying WindowsButton with LinuxGui!
Invalid object type dependency mismatch! Type: f324.WindowsButton
Type Expected: LinuxButton

Trying LinuxButton with LinuxGui!
Do(): LinuxButton
...LinuxButton works in LinuxGui!


Re: Programming to Interfaces simplification

2014-02-24 Thread Steven Schveighoffer

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