www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Interfaced programming - InterfacedProgramming.doc

reply gediminasb pmt.lt writes:
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
Jun 30 2005
next sibling parent reply "Regan Heath" <regan netwin.co.nz> writes:
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

Jun 30 2005
parent reply gediminasb pmt.lt writes:
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


Jun 30 2005
next sibling parent Chris Sauls <ibisbasenji gmail.com> writes:
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
Jun 30 2005
prev sibling parent "Regan Heath" <regan netwin.co.nz> writes:
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



Jun 30 2005
prev sibling parent pragma <pragma_member pathlink.com> writes:
In article <da0ita$qv8$1 digitaldaemon.com>, gediminasb pmt.lt says...
Interfaced programming

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
Jun 30 2005