Thread overview
Interfaced programming - InterfacedProgramming.doc
Jun 30, 2005
gediminasb
Jun 30, 2005
Regan Heath
Jun 30, 2005
gediminasb
Jun 30, 2005
Chris Sauls
Jun 30, 2005
Regan Heath
Jun 30, 2005
pragma
June 30, 2005
Interfaced programming

Using interfaces in enterprise programming has one big issue: you must to write
an implementation of methods in every class that implement this interface. This
complicates software supporting in case of large set of classes where the
interface is implemented. It would be nice to have one unit with implementation
of the interface and use it in every class that implements this interface, but
this trick is forbidden in D language.
Constructors of Delphi language met the same problem and provided an elegant
solution: they extended the language with implements directyve:

property MyInterface: ImyInterface
read FMyInterface implements IMyInterface;

Compiler forwards myMethod(…) call to FmyInterface. myMethod(…) when myMethod(…)
is member of ImyInterface.

You should implement something similar like this. Here is one of possible
solutions:
o	Programmer creates a class or class template that implements ImyInterface in
separate unit, myImplementationClass, for example.
o	In every class that is going to implement ImyInterface, programmer declares
state variable of myImplementationClass with implements directive:
MyImplementationClass xVar implements ImyInterface;
o	Compiler will forward every ImyInterface call to inner variable xVar.

This solution does not require large modifications and will provide very powerful tool for enterprise programming, especially combining it with class templates.


Gediminasb Bukauskas
gediminasb@pmt.lt
June 30, 2005
What's wrong with this:

interface Bob
{
  void foo();
}

abstract class aBob : Bob {
  void foo() { printf("abstract\n"); }
}

template tBob() {
  void foo() { printf("template\n"); }
}

class Fred : aBob {
}

class Carl {
  mixin tBob;
}

class John : aBob {
  override void foo() { printf("override\n"); }
}

void main()
{
	Fred f = new Fred();
	Carl c = new Carl();
	John j = new John();
	
	f.foo();
	c.foo();
	j.foo();
}

Fred uses an abstract class which contains the implementation. Carl uses a mixin to mix a template containing the implementation. John uses the abstract class but provides an override.

Regan

On Thu, 30 Jun 2005 10:52:26 +0000 (UTC), <gediminasb@pmt.lt> wrote:

> Interfaced programming
>
> Using interfaces in enterprise programming has one big issue: you must to write
> an implementation of methods in every class that implement this interface. This
> complicates software supporting in case of large set of classes where the
> interface is implemented. It would be nice to have one unit with implementation
> of the interface and use it in every class that implements this interface, but
> this trick is forbidden in D language.
> Constructors of Delphi language met the same problem and provided an elegant
> solution: they extended the language with implements directyve:
>
> property MyInterface: ImyInterface
> read FMyInterface implements IMyInterface;
>
> Compiler forwards myMethod(…) call to FmyInterface. myMethod(…) when myMethod(…)
> is member of ImyInterface.
>
> You should implement something similar like this. Here is one of possible
> solutions:
> o	Programmer creates a class or class template that implements ImyInterface in
> separate unit, myImplementationClass, for example.
> o	In every class that is going to implement ImyInterface, programmer declares
> state variable of myImplementationClass with implements directive:
> MyImplementationClass xVar implements ImyInterface;
> o	Compiler will forward every ImyInterface call to inner variable xVar.
>
> This solution does not require large modifications and will provide very
> powerful tool for enterprise programming, especially combining it with class
> templates.
>
>
> Gediminasb Bukauskas
> gediminasb@pmt.lt

June 30, 2005
Try to expand your example to class with two different LARGE interfaces:

interface Bob
{
void foo1 ();
…
void foo100();
}
interface Smith
{
void fpp1():
…
void fpp100();
}

class Uncle1: Bob, Smith
{
…. ??? ….
}
class Uncle2: Bob, Smith
{
…. ??? ….
}

You must to provide stubs for 200 functions in every class that implement these two interfaces! This is tedious and error prone work. Compiler will do it better.


In article <opss6jr4mv23k2f5@nrage.netwin.co.nz>, Regan Heath says...
>
>What's wrong with this:
>
>interface Bob
>{
>   void foo();
>}
>
>abstract class aBob : Bob {
>   void foo() { printf("abstract\n"); }
>}
>
>template tBob() {
>   void foo() { printf("template\n"); }
>}
>
>class Fred : aBob {
>}
>
>class Carl {
>   mixin tBob;
>}
>
>class John : aBob {
>   override void foo() { printf("override\n"); }
>}
>
>void main()
>{
>	Fred f = new Fred();
>	Carl c = new Carl();
>	John j = new John();
>
>	f.foo();
>	c.foo();
>	j.foo();
>}
>
>Fred uses an abstract class which contains the implementation. Carl uses a mixin to mix a template containing the implementation. John uses the abstract class but provides an override.
>
>Regan
>
>On Thu, 30 Jun 2005 10:52:26 +0000 (UTC), <gediminasb@pmt.lt> wrote:
>
>> Interfaced programming
>>
>> Using interfaces in enterprise programming has one big issue: you must
>> to write
>> an implementation of methods in every class that implement this
>> interface. This
>> complicates software supporting in case of large set of classes where the
>> interface is implemented. It would be nice to have one unit with
>> implementation
>> of the interface and use it in every class that implements this
>> interface, but
>> this trick is forbidden in D language.
>> Constructors of Delphi language met the same problem and provided an
>> elegant
>> solution: they extended the language with implements directyve:
>>
>> property MyInterface: ImyInterface
>> read FMyInterface implements IMyInterface;
>>
>> Compiler forwards myMethod(…) call to FmyInterface. myMethod(…) when
>> myMethod(…)
>> is member of ImyInterface.
>>
>> You should implement something similar like this. Here is one of possible
>> solutions:
>> o	Programmer creates a class or class template that implements
>> ImyInterface in
>> separate unit, myImplementationClass, for example.
>> o	In every class that is going to implement ImyInterface, programmer
>> declares
>> state variable of myImplementationClass with implements directive:
>> MyImplementationClass xVar implements ImyInterface;
>> o	Compiler will forward every ImyInterface call to inner variable xVar.
>>
>> This solution does not require large modifications and will provide very
>> powerful tool for enterprise programming, especially combining it with
>> class
>> templates.
>>
>>
>> Gediminasb Bukauskas
>> gediminasb@pmt.lt
>


June 30, 2005
In article <da0ita$qv8$1@digitaldaemon.com>, gediminasb@pmt.lt says...
>
>Interfaced programming
>
[snip]
>Constructors of Delphi language met the same problem and provided an elegant solution: they extended the language with implements directyve:

Yes, but then the authors of Java came along and decided that the Adapter pattern is good enough.  Also, D has a habit of trapping mistakes, and making lots of noise about them when it sees them, and halting compilation/execution if that's the case.  This feature seems to go against the grain with that notion.

(I don't know how experienced you are with software engineering, so I apologize in advance if this all old news.  There are some neophytes in this NG, so I'm writing this largely for their reading.)

Now we're not writing in Java, but when you get down to it: implementing an interface really should involve completely *supporting* that interface.  Its something that transcends any language, and can be found in just about any textbook on OOP.  Otherwise, you're really trying to provide boilerplate code as a shortcut.  Adapters, and multiple-inheritance thereof (using mixins in D), do a good job of supporting this need.

I'll add that if you have an interface that one would only need to partially support, it could arguably be split into multiple interfaces instead.  Good design dictates that an interface's purpose should be more or less orthogonal to other interfaces (unless they inherit each other).

This also has implications for cooperative development, where author A changes an interface and author B uses the modified version in his/her code.  Author B will now have (silently) buggy code without even so much as a peep from the compiler.

I have seen older renditions of DMD cause a cast to an interface (under certain conditions) to return a vtable of seemingly 'empty' methods.  My funcion calls were going into oblivion with no warning, contrary to the code.  Even after I deduced what was going on, it was still a huge source for bugs and error in my program.  I could expect the same kind of frustration were D augmented in the way you suggest, as now I will have no warning if I have forgotten to implement a particular method.

- EricAnderton at yahoo
June 30, 2005
gediminasb@pmt.lt wrote:
> Try to expand your example to class with two different LARGE interfaces:
> 
> interface Bob
> {
> void foo1 ();
> > void foo100();
> }
> interface Smith
> {
> void fpp1():
> > void fpp100();
> }
> 
> class Uncle1: Bob, Smith
> {
> …. ??? ….
> }
> class Uncle2: Bob, Smith
> {
> …. ??? ….
> }
> 
> You must to provide stubs for 200 functions in every class that implement these
> two interfaces! This is tedious and error prone work. Compiler will do it
> better.

Actually... no, no stubs needed.  The abstract-superparent and mixin-template methods still work.  Size makes no difference.

# class Uncle1 : Bob, Smith {
#   mixin StdBob;
#   mixin StdSmith;
# }
#
# class Uncle2 : Bob, Smith {
#   mixin StdBob;
#   mixin StdSmith;
# }

Or maybe one could create a templated parent to provide the interfaces and their standard implementations:

# class Uncle3 : Interfaces2!(Bob, Smith) {
# }

Or:

# class Uncle4 : InterfacesM2!(
#   Bob, StdBob,
#   Smith, StdSmith
# ) {
# }

Using:
# class Interfaces2(I1, I2) : I1, I2 { }
# class InterfacesM2(I1, I1M, I2, I2M) : I1, I2 {
#   mixin I1M;
#   mixin I2M;
# }

The only thing missing to make this method perfect, is variadic template arguments, though how exactly one would pull that off is beyond me.

-- Chris Sauls
June 30, 2005
If you simply want something to provide stubs so as you can fill in the contents (I can understand that), I'd suggest this was the job of a good IDE. Otherwise mixins and abstract base classes still work. Abstract base classes prevent inheritance from another class, so I tend to use mixins the whole time.

Regan

On Thu, 30 Jun 2005 12:36:22 +0000 (UTC), <gediminasb@pmt.lt> wrote:

> Try to expand your example to class with two different LARGE interfaces:
>
> interface Bob
> {
> void foo1 ();
> > void foo100();
> }
> interface Smith
> {
> void fpp1():
> > void fpp100();
> }
>
> class Uncle1: Bob, Smith
> {
> …. ??? ….
> }
> class Uncle2: Bob, Smith
> {
> …. ??? ….
> }
>
> You must to provide stubs for 200 functions in every class that implement these
> two interfaces! This is tedious and error prone work. Compiler will do it
> better.
>
>
> In article <opss6jr4mv23k2f5@nrage.netwin.co.nz>, Regan Heath says...
>>
>> What's wrong with this:
>>
>> interface Bob
>> {
>>   void foo();
>> }
>>
>> abstract class aBob : Bob {
>>   void foo() { printf("abstract\n"); }
>> }
>>
>> template tBob() {
>>   void foo() { printf("template\n"); }
>> }
>>
>> class Fred : aBob {
>> }
>>
>> class Carl {
>>   mixin tBob;
>> }
>>
>> class John : aBob {
>>   override void foo() { printf("override\n"); }
>> }
>>
>> void main()
>> {
>> 	Fred f = new Fred();
>> 	Carl c = new Carl();
>> 	John j = new John();
>> 	
>> 	f.foo();
>> 	c.foo();
>> 	j.foo();
>> }
>>
>> Fred uses an abstract class which contains the implementation. Carl uses a
>> mixin to mix a template containing the implementation. John uses the
>> abstract class but provides an override.
>>
>> Regan
>>
>> On Thu, 30 Jun 2005 10:52:26 +0000 (UTC), <gediminasb@pmt.lt> wrote:
>>
>>> Interfaced programming
>>>
>>> Using interfaces in enterprise programming has one big issue: you must
>>> to write
>>> an implementation of methods in every class that implement this
>>> interface. This
>>> complicates software supporting in case of large set of classes where the
>>> interface is implemented. It would be nice to have one unit with
>>> implementation
>>> of the interface and use it in every class that implements this
>>> interface, but
>>> this trick is forbidden in D language.
>>> Constructors of Delphi language met the same problem and provided an
>>> elegant
>>> solution: they extended the language with implements directyve:
>>>
>>> property MyInterface: ImyInterface
>>> read FMyInterface implements IMyInterface;
>>>
>>> Compiler forwards myMethod(…) call to FmyInterface. myMethod(…) when
>>> myMethod(…)
>>> is member of ImyInterface.
>>>
>>> You should implement something similar like this. Here is one of possible
>>> solutions:
>>> o	Programmer creates a class or class template that implements
>>> ImyInterface in
>>> separate unit, myImplementationClass, for example.
>>> o	In every class that is going to implement ImyInterface, programmer
>>> declares
>>> state variable of myImplementationClass with implements directive:
>>> MyImplementationClass xVar implements ImyInterface;
>>> o	Compiler will forward every ImyInterface call to inner variable xVar.
>>>
>>> This solution does not require large modifications and will provide very
>>> powerful tool for enterprise programming, especially combining it with
>>> class
>>> templates.
>>>
>>>
>>> Gediminasb Bukauskas
>>> gediminasb@pmt.lt
>>
>
>