www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Differing implementations for a function in two interfaces

reply Lionello Lunesu <lio lunesu.remove.com> writes:
Hi,

Like the subject says, I have two interfaces that both declare some 
function, say "int get();", but in the class that implements these 
interfaces I'd like to differentiate between the two.

#interface IA {
#	int get();
#}

#interface IB {
#	int get();
#}

#class C : IA, IB {
#	int get() { return 1; }
#}

I would like to implement IA.get() differently from IB.get(), but is 
this even possible? Can't find anything on this in the docs.

Actually, what I'm trying to do is create multiple foreach/opApply's in 
one class, depending on which interface you use, specifically a wrapper 
for the sqlite "sqlite3_stmt" handle. I'd like to be able to iterate the 
rows in a result set, and the fields in a row.

At the moment I do this:

#// handle wrapper, RAII
#class Command {
#	sqlite3_stmt* stmt;
#	~this() { sqlite3_finalize(stmt); }
#	Result Execute() { return new Result(this); }
#}

#class Result {
#	Command cmd;
#	// this one iterates rows; does new ResultRow(cmd)
#	int opApply( int delegate(inout ResultRow) dg );
#}

#class ResultRow {
#	Command cmd;
#	// this one iterates fields; does new ResultField(cmd,fieldno);
#	int opApply( int delegate(inout ResultField) dg );
#}

#class ResultField {
#	Command cmd;
#	uint fieldno;
#}

This works just fine, but a lot of temporary objects are created, that 
don't really contain anything new, just a reference to the Command 
object. I would like to use interfaces instead:

#interface IResult {
#	// this one iterates rows
#	int opApply( int delegate(inout IResultRow) dg );
#}

#interface IResultRow {
#	// this one iterates fields
#	int opApply( int delegate(inout ResultField) dg );
#}

#// As before, since we need to keep track of the field index
#class ResultField {
#	Command cmd;
#	uint fieldno;
#}

#class Command : IResult, IResultRow {	// handle wrapper
#	sqlite3_stmt* stmt;
#	~this() { sqlite3_finalize(stmt); }
#	IResult Execute() { return cast(IResult)this; }
#	// this one iterates rows; does cast(IResultRow)this
#	int IResult.opApply( int delegate(inout IResultRow) dg );
#	// this one iterates fields; does new ResultField(this,fieldno)
#	int IResultRow.opApply( int delegate(inout IResultField) dg );
#}

Or is there a solution to this pattern I haven't thought of yet?

All comments are appreciated :)

L.
Apr 15 2006
next sibling parent reply Chris Nicholson-Sauls <ibisbasenji gmail.com> writes:
Lionello Lunesu wrote:
 #class Command : IResult, IResultRow {    // handle wrapper

 #    int IResult.opApply( int delegate(inout IResultRow) dg );

 #    int IResultRow.opApply( int delegate(inout IResultField) dg );
 #}

I actually rather like this syntax. When I first started reading your post, this was precisely what I thought of as a possible general purpose solution. The difficulty I see is in how to select which to use at call-time. In your case, I see you use a simple `cast(Interface) object` to do so, which seems fair enough... but might there be another way to do the selection in simpler expressions? # class Foo : IA, IB { ... } // IA and IB declare: int get(); # # Foo obj = new Foo; # # // call IA.get()... ew # (cast(IA) obj).get(); # # // call IB.get()... eh # obj.get IB(); # // or # obj IB.get(); # # // call IA.get()... erm # obj.IA::get(); Just thinking. -- Chris Nicholson-Sauls
Apr 15 2006
next sibling parent BCS <BCS_member pathlink.com> writes:
In article <e1qgma$1ngm$1 digitaldaemon.com>, Chris Nicholson-Sauls says...
Lionello Lunesu wrote:
 #class Command : IResult, IResultRow {    // handle wrapper

 #    int IResult.opApply( int delegate(inout IResultRow) dg );

 #    int IResultRow.opApply( int delegate(inout IResultField) dg );
 #}

I actually rather like this syntax. When I first started reading your post, this was precisely what I thought of as a possible general purpose solution. The difficulty I see is in how to select which to use at call-time. In your case, I see you use a simple `cast(Interface) object` to do so, which seems fair enough... but might there be another way to do the selection in simpler expressions?

problems, namely, now dose a class implement an interface with inherited functions? Interface thingI { char[] getName() char[] getType() } Class foo { char[] name(){...} //no type } class bar : thingI { char[] type(){...} alias name : thingI.getName; //need not have the same name alias type : thingI.getTypr; } but this would require that bug #52 be fixed so that DMD can distinguish between overloaded function e.g. int foo(int i){...} int foo(char c){...} auto fnp = &foo; // what type is fnp? DMD makes an arbitrary selection that is context dependent.
Apr 15 2006
prev sibling parent reply Lionello Lunesu <lio lunesu.remove.com> writes:
Chris Nicholson-Sauls wrote:
 Lionello Lunesu wrote:
 #class Command : IResult, IResultRow {    // handle wrapper

 #    int IResult.opApply( int delegate(inout IResultRow) dg );

 #    int IResultRow.opApply( int delegate(inout IResultField) dg );
 #}

I actually rather like this syntax. When I first started reading your post, this was precisely what I thought of as a possible general purpose solution. The difficulty I see is in how to select which to use at call-time. In your case, I see you use a simple `cast(Interface) object` to do so, which seems fair enough... but might there be another way to do the selection in simpler expressions? # class Foo : IA, IB { ... } // IA and IB declare: int get(); # # Foo obj = new Foo; # # // call IA.get()... ew # (cast(IA) obj).get(); # # // call IB.get()... eh # obj.get IB(); # // or # obj IB.get(); # # // call IA.get()... erm # obj.IA::get(); Just thinking. -- Chris Nicholson-Sauls

Even when calling, I'd pick the "IB.get" syntax: #class C : IA, IB { # int IA.get() {..} # int IB.get() {..} #} #void main() { # C c = new C; #// c.get();//error, ambiguity # c.IA.get();//OK, calls IA.get # c.IB.get();//OK, calls IB.get #} But there's probably some syntax parsing problem I know nothing about. L.
Apr 17 2006
parent Ryan Steen <Ryan_member pathlink.com> writes:
In article <e21vvd$1sv1$1 digitaldaemon.com>, Lionello Lunesu says...

#void main() {
#  C c = new C;
#//  c.get();//error, ambiguity
#  c.IA.get();//OK, calls IA.get
#  c.IB.get();//OK, calls IB.get
#}

This example seems somehow flawed. Interfaces are in the role of assuring access to some and denying access to some other public features of the implementation, don't they? But if one has full access to the implementation as above, then their denials are ineffective. Therefore this cannot be the usual case.
Apr 18 2006
prev sibling next sibling parent reply Ryan Steen <Ryan_member pathlink.com> writes:
In article <e1qem7$1lvs$1 digitaldaemon.com>, Lionello Lunesu says...

#class Command : IResult, IResultRow {	// handle wrapper
#	sqlite3_stmt* stmt;
#	~this() { sqlite3_finalize(stmt); }
#	IResult Execute() { return cast(IResult)this; }
#	// this one iterates rows; does cast(IResultRow)this
#	int IResult.opApply( int delegate(inout IResultRow) dg );
#	// this one iterates fields; does new ResultField(this,fieldno)
#	int IResultRow.opApply( int delegate(inout IResultField) dg );
#}

I do not see the problem here because the opApply from the different interfaces do not have identical formal parameter lists. Therefore your code above is very vlose to the solution: #class Command : IResult, IResultRow { // handle wrapper # sqlite3_stmt* stmt; # ~this() { sqlite3_finalize(stmt); } # IResult Execute() { return this; } # // this one iterates rows; does cast(IResultRow)this # int opApply( int delegate(inout IResultRow) dg ); # // this one iterates fields; does new ResultField(this,fieldno) # int opApply( int delegate(inout IResultField) dg ); #}
Apr 15 2006
parent reply Lionello Lunesu <lio lunesu.remove.com> writes:
Ryan Steen wrote:
 In article <e1qem7$1lvs$1 digitaldaemon.com>, Lionello Lunesu says...
 
 #class Command : IResult, IResultRow {	// handle wrapper
 #	sqlite3_stmt* stmt;
 #	~this() { sqlite3_finalize(stmt); }
 #	IResult Execute() { return cast(IResult)this; }
 #	// this one iterates rows; does cast(IResultRow)this
 #	int IResult.opApply( int delegate(inout IResultRow) dg );
 #	// this one iterates fields; does new ResultField(this,fieldno)
 #	int IResultRow.opApply( int delegate(inout IResultField) dg );
 #}

I do not see the problem here because the opApply from the different interfaces do not have identical formal parameter lists. Therefore your code above is very vlose to the solution: #class Command : IResult, IResultRow { // handle wrapper # sqlite3_stmt* stmt; # ~this() { sqlite3_finalize(stmt); } # IResult Execute() { return this; } # // this one iterates rows; does cast(IResultRow)this # int opApply( int delegate(inout IResultRow) dg ); # // this one iterates fields; does new ResultField(this,fieldno) # int opApply( int delegate(inout IResultField) dg ); #}

Brilliant!!! Why didn't I think of that.. Indeed, it works. BUT, I could not provide the opIndex and opCall operators: #class Parameter {..} #class Command { # // return command parameter i # Parameter opIndex(uint i); # // return command parameter named n # Parameter opCall(char[] n); #} #class ResultRow { # // return field at index i # ResultField opIndex(uint i); # // return field named n # ResultField opCall(char[] n); #} So the problem in the original post still applies to opIndex and opCall. Thanks a lot for the suggestion ;) L.
Apr 16 2006
parent reply Ryan Steen <Ryan_member pathlink.com> writes:
In article <e1vbp8$1lcq$1 digitaldaemon.com>, Lionello Lunesu says...

So the problem in the original post still applies to opIndex and opCall.

Only if the formal parameter lists stay the same. Is it a good design not to have typedef'ed subtypes for fieldnames and parameternames, rowindex and columnindex?
Apr 17 2006
parent reply Lionello Lunesu <lio lunesu.remove.com> writes:
Ryan Steen wrote:
 In article <e1vbp8$1lcq$1 digitaldaemon.com>, Lionello Lunesu says...
 
 So the problem in the original post still applies to opIndex and opCall.

Only if the formal parameter lists stay the same. Is it a good design not to have typedef'ed subtypes for fieldnames and parameternames, rowindex and columnindex?

Nice idea! #typedef uint field_no; #typedef uint param_no; #interface IA { # char[] opIndex(param_no); #} #interface IB { # char[] opIndex(field_no); #} #class C : IA, IB { # char[] opIndex(param_no p) { return "param"; } # char[] opIndex(field_no p) { return "field"; } #} #void main() { # C c = new C; # IA ia = cast(IA)c; # writefln( "ia[2]=",ia[2]); # IB ib = cast(IB)c; # writefln( "ib[2]=",ib[2]); #} Excellent, really... I think I'm in love... L.
Apr 17 2006
parent reply Ryan Steen <Ryan_member pathlink.com> writes:
In article <e1vlef$21vv$1 digitaldaemon.com>, Lionello Lunesu says...
#	IA ia = cast(IA)c;
#	IB ib = cast(IB)c;

Those casts are superfluous and dangerous.
Apr 17 2006
parent Lionello Lunesu <lio lunesu.remove.com> writes:
Ryan Steen wrote:
 In article <e1vlef$21vv$1 digitaldaemon.com>, Lionello Lunesu says...
 #	IA ia = cast(IA)c;
 #	IB ib = cast(IB)c;

Those casts are superfluous and dangerous.

You're right. I first typed the mail and included the casts for clarity, and only later made a source file out of it.
Apr 17 2006
prev sibling parent reply Hasan Aljudy <hasan.aljudy gmail.com> writes:
I didn't read/undertstand your entire post, but I think what you're 
trying to achieve here can already be achieved through polymorphism.

I think you just need to redeisgn the classes a little bit.

Lionello Lunesu wrote:
 Hi,
 
 Like the subject says, I have two interfaces that both declare some 
 function, say "int get();", but in the class that implements these 
 interfaces I'd like to differentiate between the two.
 
 #interface IA {
 #    int get();
 #}
 
 #interface IB {
 #    int get();
 #}
 
 #class C : IA, IB {
 #    int get() { return 1; }
 #}
 
 I would like to implement IA.get() differently from IB.get(), but is 
 this even possible? Can't find anything on this in the docs.
 
 Actually, what I'm trying to do is create multiple foreach/opApply's in 
 one class, depending on which interface you use, specifically a wrapper 
 for the sqlite "sqlite3_stmt" handle. I'd like to be able to iterate the 
 rows in a result set, and the fields in a row.
 
 At the moment I do this:
 
 #// handle wrapper, RAII
 #class Command {
 #    sqlite3_stmt* stmt;
 #    ~this() { sqlite3_finalize(stmt); }
 #    Result Execute() { return new Result(this); }
 #}
 
 #class Result {
 #    Command cmd;
 #    // this one iterates rows; does new ResultRow(cmd)
 #    int opApply( int delegate(inout ResultRow) dg );
 #}
 
 #class ResultRow {
 #    Command cmd;
 #    // this one iterates fields; does new ResultField(cmd,fieldno);
 #    int opApply( int delegate(inout ResultField) dg );
 #}
 
 #class ResultField {
 #    Command cmd;
 #    uint fieldno;
 #}
 
 This works just fine, but a lot of temporary objects are created, that 
 don't really contain anything new, just a reference to the Command 
 object. I would like to use interfaces instead:
 
 #interface IResult {
 #    // this one iterates rows
 #    int opApply( int delegate(inout IResultRow) dg );
 #}
 
 #interface IResultRow {
 #    // this one iterates fields
 #    int opApply( int delegate(inout ResultField) dg );
 #}
 
 #// As before, since we need to keep track of the field index
 #class ResultField {
 #    Command cmd;
 #    uint fieldno;
 #}
 
 #class Command : IResult, IResultRow {    // handle wrapper
 #    sqlite3_stmt* stmt;
 #    ~this() { sqlite3_finalize(stmt); }
 #    IResult Execute() { return cast(IResult)this; }
 #    // this one iterates rows; does cast(IResultRow)this
 #    int IResult.opApply( int delegate(inout IResultRow) dg );
 #    // this one iterates fields; does new ResultField(this,fieldno)
 #    int IResultRow.opApply( int delegate(inout IResultField) dg );
 #}
 
 Or is there a solution to this pattern I haven't thought of yet?
 
 All comments are appreciated :)
 
 L.

Apr 15 2006
parent reply BCS <BCS_member pathlink.com> writes:
In article <e1riem$3jd$1 digitaldaemon.com>, Hasan Aljudy says...
I didn't read/undertstand your entire post, but I think what you're 
trying to achieve here can already be achieved through polymorphism.

I think you just need to redeisgn the classes a little bit.

interface IA { int get(); } interface IB { int get(); } class C : IA, IB { public int i; // illegal but ... int get() { return i+1; } // get for IA int get() { return i+2; } // get for IB } void main() { auto obj = new C; IA a = obj; IB b = obj; obj.i = 0; writef(a.get, \n); // should print 1 writef(b.get, \n); // should print 2 obj.i = 2; writef(a.get, \n); // should print 3 writef(b.get, \n); // should print 4 } Both "a" and "b" are actually pointing to obj but calls to "get" using them are supposed to differ. Some types of this problem could be handled by deriving classes from C but not when the interfaces must actually be dealing with the same object. Cases like this could really happen if someone needs to implement two interfaces from different libraries in the same class.
Apr 15 2006
parent reply Hasan Aljudy <hasan.aljudy gmail.com> writes:
BCS wrote:
 In article <e1riem$3jd$1 digitaldaemon.com>, Hasan Aljudy says...
 
I didn't read/undertstand your entire post, but I think what you're 
trying to achieve here can already be achieved through polymorphism.

I think you just need to redeisgn the classes a little bit.

I don't think that would (always) work. Consider the following: interface IA { int get(); } interface IB { int get(); } class C : IA, IB { public int i; // illegal but ... int get() { return i+1; } // get for IA int get() { return i+2; } // get for IB } void main() { auto obj = new C; IA a = obj; IB b = obj; obj.i = 0; writef(a.get, \n); // should print 1 writef(b.get, \n); // should print 2 obj.i = 2; writef(a.get, \n); // should print 3 writef(b.get, \n); // should print 4 } Both "a" and "b" are actually pointing to obj but calls to "get" using them are supposed to differ. Some types of this problem could be handled by deriving classes from C but not when the interfaces must actually be dealing with the same object. Cases like this could really happen if someone needs to implement two interfaces from different libraries in the same class.

I know, I'm saying, you can do this using polymorphism, along with a redesign, invloving decoupling the get method from the C class. class C { protected int i; } abstract class CGetter { abstract int get( C c ); } class CA : CGetter { int get( C c ) { return c.i + 1; } } class CB : CGetter { int get( C c ) { return c.i + 2; } } void main() { auto obj = new C; CA a = new CA; CB b = new CB; obj.i = 0; writefln(a.get(c)); // should print 1 writefln(b.get(c)); // should print 2 obj.i = 2; writefln(a.get(c)); // should print 3 writefln(b.get(c)); // should print 4 } A bit more complicated (for this simple example), but you're doing the same thing: creating new entries in a vtable, to choose different functions at runtime.
Apr 15 2006
next sibling parent reply Hasan Aljudy <hasan.aljudy gmail.com> writes:
Hasan Aljudy wrote:
 BCS wrote:
 
 In article <e1riem$3jd$1 digitaldaemon.com>, Hasan Aljudy says...

 I didn't read/undertstand your entire post, but I think what you're 
 trying to achieve here can already be achieved through polymorphism.

 I think you just need to redeisgn the classes a little bit.

I don't think that would (always) work. Consider the following: interface IA { int get(); } interface IB { int get(); } class C : IA, IB { public int i; // illegal but ... int get() { return i+1; } // get for IA int get() { return i+2; } // get for IB } void main() { auto obj = new C; IA a = obj; IB b = obj; obj.i = 0; writef(a.get, \n); // should print 1 writef(b.get, \n); // should print 2 obj.i = 2; writef(a.get, \n); // should print 3 writef(b.get, \n); // should print 4 } Both "a" and "b" are actually pointing to obj but calls to "get" using them are supposed to differ. Some types of this problem could be handled by deriving classes from C but not when the interfaces must actually be dealing with the same object. Cases like this could really happen if someone needs to implement two interfaces from different libraries in the same class.

I know, I'm saying, you can do this using polymorphism, along with a redesign, invloving decoupling the get method from the C class. class C { protected int i; } abstract class CGetter { abstract int get( C c ); } class CA : CGetter { int get( C c ) { return c.i + 1; } } class CB : CGetter { int get( C c ) { return c.i + 2; } } void main() { auto obj = new C; CA a = new CA; CB b = new CB; obj.i = 0; writefln(a.get(c)); // should print 1 writefln(b.get(c)); // should print 2 obj.i = 2; writefln(a.get(c)); // should print 3 writefln(b.get(c)); // should print 4 } A bit more complicated (for this simple example), but you're doing the same thing: creating new entries in a vtable, to choose different functions at runtime.

ouch, typo, replace a.get(c) with a.get(obj) obj.i = 0; writefln(a.get(obj)); // should print 1 writefln(b.get(obj)); // should print 2 obj.i = 2; writefln(a.get(obj)); // should print 3 writefln(b.get(obj)); // should print 4
Apr 15 2006
parent reply BCS <BCS_member pathlink.com> writes:
Two issues with this solution:

1> the solution does not use interfaces. The assumption I was working under is
that I am given a pair of interfaces that both have a function with the same
name and parameters but imply different actions. This is more or less trivial to
get around, add a constructor to the CA and CB classes that stores the object to
a member.

2> This solution breaks down in any but the most trial of cases, consider:

interface I {int get();}
interface J {int get();}

class C { int i; }

class CI : I
{
C c;
this(C cv) { c = cv; }
int get(){ return c.i + 1; }
}

class CJ : J
{
C c;
this(C cv) { c = cv; }
int get(){ return c.i + 2; }
}

// this works fine until we derive from C

class D
{
int get(){ return (i != 4)?54:42; }// must be override get in I
int get(){ return 4; }// must be override get in J
}

One solution is to make CI and CJ call C.getI and C.getJ from c, but that
requires another level or two of indirection that can be avoided with a syntax
that would allow us to dictate the mapping of class methods to interface methods



Basically, yes you can get around these issues without changing D but the
solution is substantially inferior to what could be available with some small
changes.


In article <e1rm6d$7u1$2 digitaldaemon.com>, Hasan Aljudy says...
Hasan Aljudy wrote:
 BCS wrote:
 In article <e1riem$3jd$1 digitaldaemon.com>, Hasan Aljudy says...

 I didn't read/undertstand your entire post, but I think what you're 
 trying to achieve here can already be achieved through polymorphism.

 I think you just need to redeisgn the classes a little bit.

I don't think that would (always) work. Consider the following: interface IA { int get(); } interface IB { int get(); } class C : IA, IB { public int i; // illegal but ... int get() { return i+1; } // get for IA int get() { return i+2; } // get for IB } void main() { auto obj = new C; IA a = obj; IB b = obj; obj.i = 0; writef(a.get, \n); // should print 1 writef(b.get, \n); // should print 2 obj.i = 2; writef(a.get, \n); // should print 3 writef(b.get, \n); // should print 4 } Both "a" and "b" are actually pointing to obj but calls to "get" using them are supposed to differ. Some types of this problem could be handled by deriving classes from C but not when the interfaces must actually be dealing with the same object. Cases like this could really happen if someone needs to implement two interfaces from different libraries in the same class.

I know, I'm saying, you can do this using polymorphism, along with a redesign, invloving decoupling the get method from the C class. class C { protected int i; } abstract class CGetter { abstract int get( C c ); } class CA : CGetter { int get( C c ) { return c.i + 1; } } class CB : CGetter { int get( C c ) { return c.i + 2; } } void main() { auto obj = new C; CA a = new CA; CB b = new CB; obj.i = 0; writefln(a.get(c)); // should print 1 writefln(b.get(c)); // should print 2 obj.i = 2; writefln(a.get(c)); // should print 3 writefln(b.get(c)); // should print 4 } A bit more complicated (for this simple example), but you're doing the same thing: creating new entries in a vtable, to choose different functions at runtime.

ouch, typo, replace a.get(c) with a.get(obj) obj.i = 0; writefln(a.get(obj)); // should print 1 writefln(b.get(obj)); // should print 2 obj.i = 2; writefln(a.get(obj)); // should print 3 writefln(b.get(obj)); // should print 4

Apr 15 2006
parent reply Hasan Aljudy <hasan.aljudy gmail.com> writes:
What you want is exactly what polymorphism is designed for. I really 
don't understand what's your problem.

BCS wrote:
 Two issues with this solution:
 
 1> the solution does not use interfaces. The assumption I was working under is
 that I am given a pair of interfaces that both have a function with the same
 name and parameters but imply different actions. This is more or less trivial
to
 get around, add a constructor to the CA and CB classes that stores the object
to
 a member.
 
 2> This solution breaks down in any but the most trial of cases, consider:
 
 interface I {int get();}
 interface J {int get();}
 
 class C { int i; }
 
 class CI : I
 {
 C c;
 this(C cv) { c = cv; }
 int get(){ return c.i + 1; }
 }
 
 class CJ : J
 {
 C c;
 this(C cv) { c = cv; }
 int get(){ return c.i + 2; }
 }
 
 // this works fine until we derive from C
 
 class D
 {
 int get(){ return (i != 4)?54:42; }// must be override get in I
 int get(){ return 4; }// must be override get in J
 }
 
 One solution is to make CI and CJ call C.getI and C.getJ from c, but that
 requires another level or two of indirection that can be avoided with a syntax
 that would allow us to dictate the mapping of class methods to interface
methods
 
 
 
 Basically, yes you can get around these issues without changing D but the
 solution is substantially inferior to what could be available with some small
 changes.
 
 
 In article <e1rm6d$7u1$2 digitaldaemon.com>, Hasan Aljudy says...
 
Hasan Aljudy wrote:

BCS wrote:

In article <e1riem$3jd$1 digitaldaemon.com>, Hasan Aljudy says...


I didn't read/undertstand your entire post, but I think what you're 
trying to achieve here can already be achieved through polymorphism.

I think you just need to redeisgn the classes a little bit.

I don't think that would (always) work. Consider the following: interface IA { int get(); } interface IB { int get(); } class C : IA, IB { public int i; // illegal but ... int get() { return i+1; } // get for IA int get() { return i+2; } // get for IB } void main() { auto obj = new C; IA a = obj; IB b = obj; obj.i = 0; writef(a.get, \n); // should print 1 writef(b.get, \n); // should print 2 obj.i = 2; writef(a.get, \n); // should print 3 writef(b.get, \n); // should print 4 } Both "a" and "b" are actually pointing to obj but calls to "get" using them are supposed to differ. Some types of this problem could be handled by deriving classes from C but not when the interfaces must actually be dealing with the same object. Cases like this could really happen if someone needs to implement two interfaces from different libraries in the same class.

I know, I'm saying, you can do this using polymorphism, along with a redesign, invloving decoupling the get method from the C class. class C { protected int i; } abstract class CGetter { abstract int get( C c ); } class CA : CGetter { int get( C c ) { return c.i + 1; } } class CB : CGetter { int get( C c ) { return c.i + 2; } } void main() { auto obj = new C; CA a = new CA; CB b = new CB; obj.i = 0; writefln(a.get(c)); // should print 1 writefln(b.get(c)); // should print 2 obj.i = 2; writefln(a.get(c)); // should print 3 writefln(b.get(c)); // should print 4 } A bit more complicated (for this simple example), but you're doing the same thing: creating new entries in a vtable, to choose different functions at runtime.

ouch, typo, replace a.get(c) with a.get(obj) obj.i = 0; writefln(a.get(obj)); // should print 1 writefln(b.get(obj)); // should print 2 obj.i = 2; writefln(a.get(obj)); // should print 3 writefln(b.get(obj)); // should print 4


Apr 15 2006
parent reply BCS <BCS_member pathlink.com> writes:
In article <e1s2sr$n4s$1 digitaldaemon.com>, Hasan Aljudy says...
What you want is exactly what polymorphism is designed for. I really 
don't understand what's your problem.

get a _similar_ effect but all have substantial penalties involving code complexity, speed or maintainability/extensibility If you can use you suggested approach to solve this problem I would be pleased to see it. --------------- You are given this (you may not modify it) interface I {int get();} interface J {int get();} 1) You need to make a class C that implements both I and J that has different action for I.get and J.get. 2) Classes derived from C must be able to override the action of both I.get and Jget 3) Given an instance, c, of the class C, the following statements must work. I i = c; i.get // must call the appropriate I.get even if c is of a derived type. J j = c j.get // must call the appropriate J.get even if c is of a derived type. 4) Converting a C object to an I or J interface must not rely on the overloading of the cast operation (e.i. "I i = c;" must not call any methods) 5) Must be simply extendable to interfaces with lots of function (one more function in I must not require more than one function be defined to keep C up to date) I believe these requirements for a programming solution to be vary reasonable. If I were working in a programming shop and assigned a subordinate to the problem as defined through point 2, I would expect that 3-5 would be assumed.
Apr 15 2006
next sibling parent BCS <BCS_member pathlink.com> writes:
In article <e1s7gd$r15$1 digitaldaemon.com>, BCS says...
In article <e1s2sr$n4s$1 digitaldaemon.com>, Hasan Aljudy says...
What you want is exactly what polymorphism is designed for. I really 
don't understand what's your problem.


Oops: I forgot to state my position The problem I stated before is conceptually vary easy to solve: somehow, explicitly set the contents of the vtbls used by C when cast to I or J. The solution that you proposed, while workable, is a vary poor design. It is wasteful in runtime, program size, memory usage, code size and maintenance cost.
Apr 15 2006
prev sibling next sibling parent reply Hasan Aljudy <hasan.aljudy gmail.com> writes:
BCS wrote:
 In article <e1s2sr$n4s$1 digitaldaemon.com>, Hasan Aljudy says...
 
What you want is exactly what polymorphism is designed for. I really 
don't understand what's your problem.

I don't believe that D can solve the following problem. I can see several way to get a _similar_ effect but all have substantial penalties involving code complexity, speed or maintainability/extensibility If you can use you suggested approach to solve this problem I would be pleased to see it. --------------- You are given this (you may not modify it) interface I {int get();} interface J {int get();} 1) You need to make a class C that implements both I and J that has different action for I.get and J.get. 2) Classes derived from C must be able to override the action of both I.get and Jget 3) Given an instance, c, of the class C, the following statements must work. I i = c; i.get // must call the appropriate I.get even if c is of a derived type. J j = c j.get // must call the appropriate J.get even if c is of a derived type. 4) Converting a C object to an I or J interface must not rely on the overloading of the cast operation (e.i. "I i = c;" must not call any methods) 5) Must be simply extendable to interfaces with lots of function (one more function in I must not require more than one function be defined to keep C up to date) I believe these requirements for a programming solution to be vary reasonable. If I were working in a programming shop and assigned a subordinate to the problem as defined through point 2, I would expect that 3-5 would be assumed.

I would dump these requirements, talk to the guy who set them, and try to figure out what problem he was trying to solve, then I'd make a better design.
 The problem I stated before is conceptually vary easy to solve: somehow,
 explicitly set the contents of the vtbls used by C when cast to I or 

 solution that you proposed, while workable, is a vary poor design. It is
 wasteful in runtime, program size, memory usage, code size and 

It's not very easy, and I don't see how it improves performance. 1. It requires a substantial change to the grammar; namely, function names are not simply identifiers any more. 2. I don't see where's the performance gain; you're still using vtables. I don't even see how it's supposed to be a "better design".
Apr 15 2006
parent BCS <BCS_member pathlink.com> writes:
In article <e1s99b$sop$1 digitaldaemon.com>, Hasan Aljudy says...
BCS wrote:
 In article <e1s2sr$n4s$1 digitaldaemon.com>, Hasan Aljudy says...
 
What you want is exactly what polymorphism is designed for. I really 
don't understand what's your problem.

I don't believe that D can solve the following problem. I can see several way to get a _similar_ effect but all have substantial penalties involving code complexity, speed or maintainability/extensibility If you can use you suggested approach to solve this problem I would be pleased to see it. --------------- You are given this (you may not modify it) interface I {int get();} interface J {int get();} 1) You need to make a class C that implements both I and J that has different action for I.get and J.get. 2) Classes derived from C must be able to override the action of both I.get and Jget 3) Given an instance, c, of the class C, the following statements must work. I i = c; i.get // must call the appropriate I.get even if c is of a derived type. J j = c j.get // must call the appropriate J.get even if c is of a derived type. 4) Converting a C object to an I or J interface must not rely on the overloading of the cast operation (e.i. "I i = c;" must not call any methods) 5) Must be simply extendable to interfaces with lots of function (one more function in I must not require more than one function be defined to keep C up to date) I believe these requirements for a programming solution to be vary reasonable. If I were working in a programming shop and assigned a subordinate to the problem as defined through point 2, I would expect that 3-5 would be assumed.

I would dump these requirements, talk to the guy who set them, and try to figure out what problem he was trying to solve, then I'd make a better design.

say that the interfaces are part of closed source libs, as such the only part that is available for redesign is that part that is being designed by the hypothetical subordinate.
 The problem I stated before is conceptually vary easy to solve: somehow,
 explicitly set the contents of the vtbls used by C when cast to I or 
 J. The
 solution that you proposed, while workable, is a vary poor design. It is
 wasteful in runtime, program size, memory usage, code size and maintenance 
cost.

It's not very easy, and I don't see how it improves performance. 1. It requires a substantial change to the grammar;

This is exactly what I am saying should be done
 namely, function names are not simply identifiers any more.

Not necessarily a syntax like the following wouldn't require any change to the function definition syntax. Also it would allow a function to implement an interface without having the same name as the function in the interface (useful if that name is already used by a inherited class). class C : I, J { int getI(){...} int getI(){...} alias getI I.get; alias getJ J.get; }
2. I don't see where's the performance gain; you're still using vtables.

Yes but only one vtable and only one level of function call. Alternate solutions require the use of otherwise unneeded object with methods that simply wrap other methods. I would consider that pure waste.
I don't even see how it's supposed to be a "better design".

product. I consider this objective to be of great importance, more so than the how easy it is to write the program (and to some degree the simplicity of the language). From this perspective, all available solutions to the problem are wistful. Some people take the opposite view, which supports different solutions.
Apr 16 2006
prev sibling parent reply "Derek Parnell" <derek psych.ward> writes:
On Sun, 16 Apr 2006 11:43:41 +1000, BCS <BCS_member pathlink.com> wrote:

 In article <e1s2sr$n4s$1 digitaldaemon.com>, Hasan Aljudy says...
 What you want is exactly what polymorphism is designed for. I really
 don't understand what's your problem.

several way to get a _similar_ effect but all have substantial penalties involving code complexity, speed or maintainability/extensibility If you can use you suggested approach to solve this problem I would be pleased to see it. --------------- You are given this (you may not modify it) interface I {int get();} interface J {int get();}

I understood that an 'interface' was just a way of stating that the methods named in it must be implemented by any class that is derived from the interface. In other words, that the class must implement a method with the same name and parameter signature. So if two interfaces have the same method defined, then the class that is derived from both must define a method (one method) of the same name etc...
 1) You need to make a class C that implements both I and J that has  
 different
 action for I.get and J.get.

You can't do this in one class. I guess you can do ... class IC: I { int get(){ return 1; } } class JC: J { int get(){ return 2; } } class C { IC i; JC j; . . . } C c = new C; c.i.get; // must call the appropriate I.get even if c is of a derived type. c.j.get; // must call the appropriate J.get even if c is of a derived type.
 2) Classes derived from C must be able to override the action of both  
 I.get and
 J.get

But there are no actions defined for these interface methods, just signatures. There is nothing to override.
 3) Given an instance, c, of the class C, the following statements must  
 work.
 I i = c;
 i.get	// must call the appropriate I.get even if c is of a derived type.
 J j = c
 j.get	// must call the appropriate J.get even if c is of a derived type.

 4) Converting a C object to an I or J interface must not rely on the  
 overloading
 of the cast operation (e.i. "I i = c;" must not call any methods)

 5) Must be simply extendable to interfaces with lots of function (one  
 more
 function in I must not require more than one function be defined to keep  
 C up to
 date)

It seems that 'interface' in D means something different from what you mean by the term. -- Derek Parnell Melbourne, Australia
Apr 15 2006
next sibling parent BCS <BCS_member pathlink.com> writes:
In article <op.s72xewiy6b8z09 ginger.vic.bigpond.net.au>, Derek Parnell says...
On Sun, 16 Apr 2006 11:43:41 +1000, BCS <BCS_member pathlink.com> wrote:

 In article <e1s2sr$n4s$1 digitaldaemon.com>, Hasan Aljudy says...
 What you want is exactly what polymorphism is designed for. I really
 don't understand what's your problem.

several way to get a _similar_ effect but all have substantial penalties involving code complexity, speed or maintainability/extensibility If you can use you suggested approach to solve this problem I would be pleased to see it. --------------- You are given this (you may not modify it) interface I {int get();} interface J {int get();}

I understood that an 'interface' was just a way of stating that the methods named in it must be implemented by any class that is derived from the interface. In other words, that the class must implement a method with the same name and parameter signature. So if two interfaces have the same method defined, then the class that is derived from both must define a method (one method) of the same name etc...

Yes, mostly. However if I understand them correctly, an interface also defines a actual data structure that consist of a context pointer (the pointer to the object) and a separate vtbl pointer that points to a vtbl that is different from the vtbl of the implementing class. The point of this is that each interface has a layout for this vtbl that is independent of the layout of the classes vtbl. This has the effect that code that uses a interface only needs to known that layout and not anything about the class it is actually using.
 1) You need to make a class C that implements both I and J that has  
 different
 action for I.get and J.get.

You can't do this in one class. I guess you can do ... class IC: I { int get(){ return 1; } } class JC: J { int get(){ return 2; } } class C { IC i; JC j; . . . } C c = new C; c.i.get; // must call the appropriate I.get even if c is of a derived type. c.j.get; // must call the appropriate J.get even if c is of a derived type.
 2) Classes derived from C must be able to override the action of both  
 I.get and
 J.get

But there are no actions defined for these interface methods, just signatures. There is nothing to override.

The point is that if E is derived from C, than the effect of casting a E object to type I and calling get can be defined in E class E : C { int get() { /* new functionality*/ ...} } E e = new E; I i = e; i.get; // calls the function in E
 3) Given an instance, c, of the class C, the following statements must  
 work.
 I i = c;
 i.get	// must call the appropriate I.get even if c is of a derived type.
 J j = c
 j.get	// must call the appropriate J.get even if c is of a derived type.

 4) Converting a C object to an I or J interface must not rely on the  
 overloading
 of the cast operation (e.i. "I i = c;" must not call any methods)

 5) Must be simply extendable to interfaces with lots of function (one  
 more
 function in I must not require more than one function be defined to keep  
 C up to
 date)

It seems that 'interface' in D means something different from what you mean by the term.

I may be totally wrong, but I think that interfaces are a bit more than what you are thinking of. The documentation I have found on them is kind of thin and doesn't do a good job of describing what they actually are doing behind the scenes. Most of this I have had to puzzle out my self.
-- 
Derek Parnell
Melbourne, Australia

Apr 16 2006
prev sibling parent reply Lionello Lunesu <lio lunesu.remove.com> writes:
Consider this:

Two interfaces are part of different third party modules. One module 
wants you to provide an implementation for interface IA and a completely 
different module needs some interface IB. They are completely unrelated.

No problem at all. Your application class can easily interface with both:

class C : IA, IB
{
   // implement all of IA's methods
   ...
   // implement all of IB's methods
   ...
}

And you provide cast(IA)this to module A and cast(IB)this to module B. 
No worries.

After some time, a new version has come out for both the third party 
modules, each with some added functionality. However, all programmers 
being human (last time I checked) they're pretty bad at randomness and 
they both declared a method "int get()" in their interfaces.

Now you're in trouble. There's no way you can provide one implementation 
for both "int get()"s, since they are completely unrelated. IA.get is 
used in a completely different context from IB.get.

Now what? Redesign the whole app and make multiple classes? I wish there 
was another way.

L.
Apr 16 2006
parent reply Ryan Steen <Ryan_member pathlink.com> writes:
In article <e1vci0$1luu$1 digitaldaemon.com>, Lionello Lunesu says...
They are completely unrelated.
Now what? Redesign the whole app and make multiple classes?

Yes. Such design is flawed: to implement two completely unrelated interfaces in one single class.
Apr 17 2006
next sibling parent Hasan Aljudy <hasan.aljudy gmail.com> writes:
Ryan Steen wrote:
 In article <e1vci0$1luu$1 digitaldaemon.com>, Lionello Lunesu says...
 
They are completely unrelated.
Now what? Redesign the whole app and make multiple classes?

Yes. Such design is flawed: to implement two completely unrelated interfaces in one single class.

Yeah, if you implement completely unrelated interfaces in one class .. you only have yourself to blame.
Apr 17 2006
prev sibling next sibling parent reply Lionello Lunesu <lio lunesu.remove.com> writes:
Ryan Steen wrote:
 In article <e1vci0$1luu$1 digitaldaemon.com>, Lionello Lunesu says...
 They are completely unrelated.
 Now what? Redesign the whole app and make multiple classes?

Yes. Such design is flawed: to implement two completely unrelated interfaces in one single class.

I don't agree. The interfaces might be unrelated, but they can still both apply to the class needing them. IA might be an interface for the output/GUI and IB for the input. L.
Apr 17 2006
parent reply Ryan Steen <Ryan_member pathlink.com> writes:
In article <e1vlnb$226i$1 digitaldaemon.com>, Lionello Lunesu says...
IA might be an interface for the 
output/GUI and IB for the input.

Yes, but what might cause the need to have the implementation in one class? And if there is really a need what hinders a virtual split of that implenting class? IA --> CA <-- C --> CB <-- IB where --> and <-- denote inheretance?
Apr 17 2006
next sibling parent reply Lionello Lunesu <lio lunesu.remove.com> writes:
Ryan Steen wrote:
 In article <e1vlnb$226i$1 digitaldaemon.com>, Lionello Lunesu says...
 IA might be an interface for the 
 output/GUI and IB for the input.

Yes, but what might cause the need to have the implementation in one class? And if there is really a need what hinders a virtual split of that implenting class? IA --> CA <-- C --> CB <-- IB where --> and <-- denote inheretance?

Can't inherit from 2 classes, only interfaces ;) L.
Apr 17 2006
parent Ryan Steen <Ryan_member pathlink.com> writes:
In article <e1vroh$2805$2 digitaldaemon.com>, Lionello Lunesu says...

Can't inherit from 2 classes, only interfaces ;)

Correct. But I do not remember a request, that one has to inheret vom class C splitted into CA and CB. The implementation is shielded by the interfaces, isn't it?
Apr 17 2006
prev sibling parent reply Chris Nicholson-Sauls <ibisbasenji gmail.com> writes:
Ryan Steen wrote:
 In article <e1vlnb$226i$1 digitaldaemon.com>, Lionello Lunesu says...
 
IA might be an interface for the 
output/GUI and IB for the input.

Yes, but what might cause the need to have the implementation in one class? And if there is really a need what hinders a virtual split of that implenting class? IA --> CA <-- C --> CB <-- IB where --> and <-- denote inheretance?

Here you lose encapsulation, wherein you are basically having to create a C, then ask it for its CA and later for its CB, and the CA/CB classes (inner classes, maybe?) have to know their parent object and ask it for the real data and behaviors. Ew, ew, ew. (Although at least inner classes won't need the parent pointer, once we settle on some kind of 'parent' or 'outer' keyword.) -- Chris Nicholson-Sauls
Apr 17 2006
next sibling parent Ryan Steen <Ryan_member pathlink.com> writes:
In article <e20j3q$6lu$1 digitaldaemon.com>, Chris Nicholson-Sauls says...
Here you lose encapsulation

Yes. But my suggestion does not work anyway, because CA and CB must reimplement the interfaces. Sorry.
Apr 17 2006
prev sibling parent BCS <BCS_member pathlink.com> writes:
Chris Nicholson-Sauls wrote:
 Ryan Steen wrote:
 
 In article <e1vlnb$226i$1 digitaldaemon.com>, Lionello Lunesu says...

 IA might be an interface for the output/GUI and IB for the input.

Yes, but what might cause the need to have the implementation in one class? And if there is really a need what hinders a virtual split of that implenting class? IA --> CA <-- C --> CB <-- IB where --> and <-- denote inheretance?

Here you lose encapsulation, wherein you are basically having to create a C, then ask it for its CA and later for its CB, and the CA/CB classes (inner classes, maybe?) have to know their parent object and ask it for the real data and behaviors. Ew, ew, ew.

I fully agree.
(Although at least inner 
 classes won't need the parent pointer,

yes but only because its already hidden in there by the compiler
 once we settle on some kind of
 'parent' or 'outer' keyword.)
 
 -- Chris Nicholson-Sauls

Apr 17 2006
prev sibling parent reply BCS <BCS_member pathlink.com> writes:
Ryan Steen wrote:
 In article <e1vci0$1luu$1 digitaldaemon.com>, Lionello Lunesu says...
 
They are completely unrelated.
Now what? Redesign the whole app and make multiple classes?

Yes. Such design is flawed: to implement two completely unrelated interfaces in one single class.

// ABC inc.'s DB lib (closed source lib) interface DatabaseItemInterface { ... int get(); // load the data from the DB into the object, return something ... } // XYZ corp.'s finance framework (closed source lib) interface PerchaseRequest { ... int get(); // return the PO number for this item ... } // now, implement a finance database
Apr 17 2006
parent reply Ryan Steen <Ryan_member pathlink.com> writes:
In article <e212nr$o5p$1 digitaldaemon.com>, BCS says...

interface DatabaseItemInterface
interface PerchaseRequest
// now, implement a finance database

I do not understand this exercise. There are two closed source libs for which I have to provide the implementation? If there are no more constraints, then it is possible to write classes which implement the two interfacec by wrapping the appropriate functions from the main application, the finance database. But I already said it elsewhere, D would be better off with some features for renaming or aliasing interface content as well as interfaces themselves.
Apr 17 2006
parent BCS <BCS_member pathlink.com> writes:
In article <e219lb$1193$1 digitaldaemon.com>, Ryan Steen says...
In article <e212nr$o5p$1 digitaldaemon.com>, BCS says...

interface DatabaseItemInterface
interface PerchaseRequest
// now, implement a finance database

I do not understand this exercise. There are two closed source libs for which I have to provide the implementation?

Make a database item class using the database provided interface that can be used by the finance lib (e.i. implements the finance interface). The need for the interfaces comes from the need for library functions to handle the objects. Inside of the libs the "get" functions will be called using the interfaces.
If there are no more constraints, then it is possible to write classes which
implement the two interfacec by wrapping the appropriate functions from the 
 main application, the finance database.

I'm not sure what you are saying?? Something like this (extra classes and objects) has bean suggested but it looks really messy to me.
But I already said it elsewhere, D would be better off with some features for
renaming or aliasing interface content as well as interfaces themselves. 

Yes, this is exactly what I am suggesting. I have already outlined my suggested syntax elsewhere.
Apr 17 2006
prev sibling parent Lionello Lunesu <lio lunesu.remove.com> writes:
Hasan Aljudy wrote:

<snip>

 A bit more complicated (for this simple example), but you're doing the 
 same thing: creating new entries in a vtable, to choose different 
 functions at runtime.

Your solution is pretty close to what I had in the first place. The reason I didn't like it was because of all the "new"s. CA and CB don't contain any data, but must be new'ed nonetheless. Furthermore, in your code you have to keep passing the C class to each call on CA and CB: not a viable solution. L.
Apr 16 2006