www.digitalmars.com         C & C++   DMDScript  

D - common implementations for interfaces

reply "Scott Pigman" <scottpig1 attbi.com> writes:
Regarding classes and interfaces:

A common problem i find when using interfaces is that i'll have
several classes which all use the same interface, and for which i
intend to use the same implementations for the member functions
defined in the implementation.  this results in a bunch of
cut-and-paste code in the various classes, and introduces problems
maintaining the code.  so, i'm proposing an "implementation" construct
to simplify (i hope) this situation.  it'd look something like this:

interface FooInt
{
	void a();
	int b();
}

implementation FooImpl : FooInt
{
	// FooImpl provides code to implement the interface Foo, but
	// is not a class and can't be instantiated.

	void a(){ printf("A"); }
	int b() { return 1; }
}

then the class definitions could implement the FooInt interface, using
the FooImpl implentation:

class Foo : FooInt uses FooImpl
{
	// implementation of a() and b() taken from FooImpl
}

class Bar : FooInt uses FooImpl
{

	// implementation of a() and b() also taken from FooImpl
}

classes would of course be free to ignore the impl code:

class Fu : FooInt
{
	void a() { printf("i'm my own impl"); }
	
	int b() { printf("me too!);
		  return -1000; }
}

or be free to pick and choose what they want to use:

class Barre : FooInt
{
	void a() uses FooImpl; // code for a taken from FooImpl
	int b() { return -1000; } // customized impl used here.
}

other thoughts:
i don't think i'd require FooImpl to implement every
method in FooInt - although it certainly couldn't add any new public
methods (private methods that facilatate implementing the public
interface's method are ok).  methods not provided by the impl would
have to be explicly defined in each class that uses the corresponding
interface (or use a different impl module).

although it's more typeing (boo!) it might be a good idea to still
require the class to list the methods whose implementations are
provided by FooImpl.  perhaps the following notation:

class Bah : FooInt // new england version of Bar ;-)
{
	using FooImpl:  // explicitly list the methods taken form FooImpl.
	      void a();
	      int b();

	double c(){....} // something not from FooInt - has to be
			 // implemented here.
}
	


this would also make it easy to change implementations of key code by
simply changing the implentation that the "uses" clause refers to and
relinking, such as in the "stategy" design pattern.

thoughts/comments/suggestions/derision?

-scott
Jan 19 2003
next sibling parent reply "Martin M. Pedersen" <mmp www.moeller-pedersen.dk> writes:
Hi,

I have had thoughts about this too, or something very similar. Your proposal
looks much like multiple inheritance too me. I had thought of another
solution to the same problem, not involving multiple-inheritance.

I would like to have a way to easily delegate an interface to a member
variable that also implements the interface. Something like this:

    interface FooInterface
    {
        void a();
        int b();
    }

    class FooImpl implements FooInterface {
        void a() { ... }
        int b() { ... }
    }

    class FooWrapper implements FooInt {
        FooInterface foo implements FooInt;
        this() {
           foo = new FooImpl();
        }
        void a() { /* overrides foo.a() */ }
    }

In this case, the compiler should generate the code to delegate
FooWrapper.b() to FooWrapper.foo.a(). It would also work if foo was assigned
a new value - then FooWrapper.b() would be delegated to the new object -
possibly of another class also implementing the interface.

Design patterns are *HOT*, and delegation is used everywhere with them. A
mechanism like this would make it easier to use them. It is also nearly
multiple inheritance, but without the problems with multiple inheritance
because it is explicit if a member is used to implement an interface.

Regards,
Martin M. Pedersen


"Scott Pigman" <scottpig1 attbi.com> wrote in message
news:b0etkg$10g$1 digitaldaemon.com...
 Regarding classes and interfaces:

 A common problem i find when using interfaces is that i'll have
 several classes which all use the same interface, and for which i
 intend to use the same implementations for the member functions
 defined in the implementation.  this results in a bunch of
 cut-and-paste code in the various classes, and introduces problems
 maintaining the code.  so, i'm proposing an "implementation" construct
 to simplify (i hope) this situation.  it'd look something like this:

 interface FooInt
 {
 void a();
 int b();
 }

 implementation FooImpl : FooInt
 {
 // FooImpl provides code to implement the interface Foo, but
 // is not a class and can't be instantiated.

 void a(){ printf("A"); }
 int b() { return 1; }
 }

 then the class definitions could implement the FooInt interface, using
 the FooImpl implentation:

 class Foo : FooInt uses FooImpl
 {
 // implementation of a() and b() taken from FooImpl
 }

 class Bar : FooInt uses FooImpl
 {

 // implementation of a() and b() also taken from FooImpl
 }

 classes would of course be free to ignore the impl code:

 class Fu : FooInt
 {
 void a() { printf("i'm my own impl"); }

 int b() { printf("me too!);
   return -1000; }
 }

 or be free to pick and choose what they want to use:

 class Barre : FooInt
 {
 void a() uses FooImpl; // code for a taken from FooImpl
 int b() { return -1000; } // customized impl used here.
 }

 other thoughts:
 i don't think i'd require FooImpl to implement every
 method in FooInt - although it certainly couldn't add any new public
 methods (private methods that facilatate implementing the public
 interface's method are ok).  methods not provided by the impl would
 have to be explicly defined in each class that uses the corresponding
 interface (or use a different impl module).

 although it's more typeing (boo!) it might be a good idea to still
 require the class to list the methods whose implementations are
 provided by FooImpl.  perhaps the following notation:

 class Bah : FooInt // new england version of Bar ;-)
 {
 using FooImpl:  // explicitly list the methods taken form FooImpl.
       void a();
       int b();

 double c(){....} // something not from FooInt - has to be
 // implemented here.
 }



 this would also make it easy to change implementations of key code by
 simply changing the implentation that the "uses" clause refers to and
 relinking, such as in the "stategy" design pattern.

 thoughts/comments/suggestions/derision?

 -scott

Jan 19 2003
next sibling parent "Scott Pigman" <scottpig1 attbi.com> writes:
On Sun, 19 Jan 2003 21:46:05 +0100, Martin M. Pedersen wrote:

 Hi,
 
 I have had thoughts about this too, or something very similar. Your
 proposal looks much like multiple inheritance too me. I had thought of
 another solution to the same problem, not involving
 multiple-inheritance.
 
 

can't be instantiated and doesn't represent a new type. whether or not it introduces MI type problems which we're trying to avoid, i'm frankly not certain of. my instinct is that it might be okay since "A reimplemented interface must implement all the interface functions, it does not inherit them from a super class" as it says on the web page. now, i'm going to try to see if i understand what you're proposing. more later. -sp
Jan 19 2003
prev sibling next sibling parent reply "Scott Pigman" <scottpig1 attbi.com> writes:
i like your idea.  can't say i'll give up on mine yet, but you've given me
food for thought.  of course, i'm nobody that gets to say what gets put
into the language.  comments are embedded...

on Sun, 19 Jan 2003 21:46:05 +0100, Martin M. Pedersen wrote:

 
 I would like to have a way to easily delegate an interface to a member
 variable that also implements the interface. Something like this:
 
     interface FooInterface
     {
         void a();
         int b();
     }
 
     class FooImpl implements FooInterface {
         void a() { ... }
         int b() { ... }
     }

i think i'm following you, but where does FooInt come from?
     class FooWrapper implements FooInt {
         FooInterface foo implements FooInt;
         this() {
            foo = new FooImpl();
         }
         void a() { /* overrides foo.a() */ }
     }
 
 In this case, the compiler should generate the code to delegate
 FooWrapper.b() to FooWrapper.foo.a(). It would also work if foo was assigned
 a new value - then FooWrapper.b() would be delegated to the new object -
 possibly of another class also implementing the interface.

hmmmm... so the implementation could be changed at runtime, something that my idea doesn't support. does that introduce problems w/ the compiler/optimization/performance? i don't know, just asking.
 Design patterns are *HOT*, and delegation is used everywhere with them. A

maybe start a new thread to discuss ways of implementing design patterns in D?
 mechanism like this would make it easier to use them. It is also nearly
 multiple inheritance, but without the problems with multiple inheritance
 because it is explicit if a member is used to implement an interface.
 
 Regards,
 Martin M. Pedersen
 

Jan 19 2003
parent "Martin M. Pedersen" <mmp www.moeller-pedersen.dk> writes:
Hi,

 hmmmm... so the implementation could be changed at runtime, something that
 my idea doesn't support.  does that introduce problems w/ the
 compiler/optimization/performance?  i don't know, just asking.

I guess Walter is the expert in this area. However, I expect that the code generated for the indirection would be a JMP, not a call.
 maybe start a new thread to discuss ways of implementing design patterns

Not a bad idea at all. Regards, Martin M. Pedersen
Jan 19 2003
prev sibling parent Antti Sykari <jsykari gamma.hut.fi> writes:
"Martin M. Pedersen" <mmp www.moeller-pedersen.dk> writes:
 "Scott Pigman" <scottpig1 attbi.com> wrote in message
 news:b0etkg$10g$1 digitaldaemon.com...
 Regarding classes and interfaces:

 A common problem i find when using interfaces is that i'll have
 several classes which all use the same interface, and for which i
 intend to use the same implementations for the member functions
 defined in the implementation.  this results in a bunch of
 cut-and-paste code in the various classes, and introduces problems
 maintaining the code.  so, i'm proposing an "implementation" construct
 to simplify (i hope) this situation.  it'd look something like this:

I have had thoughts about this too, or something very similar. Your proposal looks much like multiple inheritance too me. I had thought of another solution to the same problem, not involving multiple-inheritance.

I have the assumption that multiple inheritance is OK when it is applied to classes that don't have any member variables. The problems of MI come into picture when we need to think of sharing (or duplicating) the representation of common base classes, and then things get hairy also from the implementation side. Having said that, multiple inheritance in the code sharing sense seems not to hurt performance or compiler complexity any more than interface inheritance does. And, contrary to the opinion presented in the paper (the URL of which appeared in this thread somewhere), I also think that an interface with a default implementation would be no less an interface. They already do contain assertions, testing code (hmm, there's a challenge) and pre- and postconditions (do they? At least they should *g* In Eiffel at least...) For example, if the interface provides several ways to do one thing, providing a default implementation might come handy: interface OStream { // Put a character. // - No default implementation provided. void put(char c); // Put a buffer of characters. (For efficiency reasons) // - A naive default implementation, provided to make implementing // the class easier // - Implemented in terms of put(char); void put(char[] cs) { for (c in cs) { put(c); } } } A client class implementing OStream in an XP-like test-first fashion might just override put(char), then compile and test, and then proceed to implement the more efficient put(char[]). One might even decide to implement two methods in terms of each other to make it easier to implement the interface if put(char[]) is straightforward to implement: // Output stream. // Override at least one of put(char), put(char[]) to make it // instantiable. interface OStream { void put(char c) { char[1] cs = { c }; put(cs); } void put(char[] c) { for (c in cs) { put(c); } } } This, of course, requires some kind of dependency analysis when the interface gets implemented, so that we don't get infinite recursion at runtime. -Antti
Jan 21 2003
prev sibling parent Jeff Siegel <jsiegel ualberta.ca> writes:
Scott Pigman wrote:
 Regarding classes and interfaces:
 
 A common problem i find when using interfaces is that i'll have
 several classes which all use the same interface, and for which i
 intend to use the same implementations for the member functions
 defined in the implementation.  this results in a bunch of
 cut-and-paste code in the various classes, and introduces problems
 maintaining the code.  so, i'm proposing an "implementation" construct
 to simplify (i hope) this situation.  it'd look something like this:
 

This is something some researches are looking into with Java. Basically they're adding multiple code inheritance to Java interfaces: http://www.cs.ualberta.ca/~duane/pdf/2003preprintmi.pdf Something to keep in mind. :) Jeff
Jan 19 2003