Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
January 19, 2003 common implementations for interfaces | ||||
---|---|---|---|---|
| ||||
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 |
January 19, 2003 Re: common implementations for interfaces | ||||
---|---|---|---|---|
| ||||
Posted in reply to Scott Pigman | 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 > > |
January 19, 2003 Re: common implementations for interfaces | ||||
---|---|---|---|---|
| ||||
Posted in reply to Martin M. Pedersen | 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.
>
>
it's not intended to be Multiple inheritence, since the FooImpl i describe 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
|
January 19, 2003 Re: common implementations for interfaces | ||||
---|---|---|---|---|
| ||||
Posted in reply to Martin M. Pedersen | 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 > |
January 19, 2003 Re: common implementations for interfaces | ||||
---|---|---|---|---|
| ||||
Posted in reply to Scott Pigman | 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 in D? Not a bad idea at all. Regards, Martin M. Pedersen |
January 19, 2003 Re: common implementations for interfaces | ||||
---|---|---|---|---|
| ||||
Posted in reply to Scott Pigman | 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 |
January 21, 2003 Re: common implementations for interfaces | ||||
---|---|---|---|---|
| ||||
Posted in reply to Martin M. Pedersen | "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:
>>
> 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 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
|
Copyright © 1999-2021 by the D Language Foundation