www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - interface function overloading

reply %u <e ee.com> writes:
Isn't it possible to have a hierarchy in interface definitions such that it is
possible to overload according to best interface match?

This now won't compile due to multiple matches.

----
module main;

interface I1{}
interface I2 : I1{}

class C : I2{
  this(){}
}

void func(I1 i){}
void func(I2 i){}

void main(){
  func(new C());
}
----
Jan 08 2011
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday 08 January 2011 22:01:11 %u wrote:
 Isn't it possible to have a hierarchy in interface definitions such that it
 is possible to overload according to best interface match?
 
 This now won't compile due to multiple matches.
 
 ----
 module main;
 
 interface I1{}
 interface I2 : I1{}
 
 class C : I2{
   this(){}
 }
 
 void func(I1 i){}
 void func(I2 i){}
 
 void main(){
   func(new C());
 }
 ----
Very little - if anything - in the way of overloading in D works by "best match." It pretty much always has to be exact or implicitly convertible and be the _only_ option which is implicitly convertible. Sometimes, it can be pretty annoying, but it's done to avoid cases where you accidentally call one function when you mean another, like you can get in C++ fairly easily. Take a look at http://www.digitalmars.com/d/2.0/hijack.html - Jonathan M Davis
Jan 08 2011
parent reply %u <e ee.com> writes:
== Quote from Jonathan M Davis (jmdavisProg gmx.com)'s article
 On Saturday 08 January 2011 22:01:11 %u wrote:
 Isn't it possible to have a hierarchy in interface definitions such that it
 is possible to overload according to best interface match?

 This now won't compile due to multiple matches.

 ----
 module main;

 interface I1{}
 interface I2 : I1{}

 class C : I2{
   this(){}
 }

 void func(I1 i){}
 void func(I2 i){}

 void main(){
   func(new C());
 }
 ----
Very little - if anything - in the way of overloading in D works by "best match." It pretty much always has to be exact or implicitly convertible and be the _only_ option which is implicitly convertible. Sometimes, it can be pretty annoying, but it's done to avoid cases where you accidentally call one function when you mean another, like you can get in C++ fairly easily. Take a look at http://www.digitalmars.com/d/2.0/hijack.html - Jonathan M Davis
I see, cast(ugly:) seems to work. func(cast(I2)(new C())); Thanks.
Jan 08 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
%u:

   func(cast(I2)(new C()));
That code smells a bit (http://en.wikipedia.org/wiki/Code_smell ). Bye, bearophile
Jan 09 2011
parent reply %u <e ee.com> writes:
== Quote from bearophile (bearophileHUGS lycos.com)'s article
 %u:
   func(cast(I2)(new C()));
That code smells a bit (http://en.wikipedia.org/wiki/Code_smell ). Bye, bearophile
Extract the construction and you get: ---- module main; interface I1{} interface I2 : I1{} class C : I2{ this(){} } void func(I1 i){} void func(I2 i){} void main(){ C c = new C(); func( cast(I2)c ); } ---- What is the deeper problem in this little snippet? Or do you mean there is something wrong if you encounter this pattern. I don't think it's really that much worse than renaming one(or both) of the funcs. It forces you to cast all class:I2 objects to the func you want called, but all class:I1 objects already call the correct func. I think different named funcs is a better solution, but I don't think the cast solution exemplifies a pattern of indication to a deeper problem.
Jan 09 2011
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
%u:

 What is the deeper problem in this little snippet?
 Or do you mean there is something wrong if you encounter this pattern.
You are right, sorry :-) Bye, bearophile
Jan 09 2011
prev sibling parent reply Stanislav Blinov <blinov loniir.ru> writes:
09.01.2011 15:22, %u пишет:
 == Quote from bearophile (bearophileHUGS lycos.com)'s article
 %u:
    func(cast(I2)(new C()));
That code smells a bit (http://en.wikipedia.org/wiki/Code_smell ). Bye, bearophile
Extract the construction and you get: ---- module main; interface I1{} interface I2 : I1{} class C : I2{ this(){} } void func(I1 i){} void func(I2 i){} void main(){ C c = new C(); func( cast(I2)c ); } ---- What is the deeper problem in this little snippet? Or do you mean there is something wrong if you encounter this pattern. I don't think it's really that much worse than renaming one(or both) of the funcs. It forces you to cast all class:I2 objects to the func you want called, but all class:I1 objects already call the correct func. I think different named funcs is a better solution, but I don't think the cast solution exemplifies a pattern of indication to a deeper problem.
In C++ I sometimes have similar problems, especially with multiple inheritance. Though, as Jonathan mentioned, those problems are even more annoying because of hijacking: you don't always immediately notice them. Long ago I've decided to always employ conversion methods for such cases, which in D might look like this: class C : I2{ I1 toI1() { return this; } I2 toI2() { return this; } } This unclutters the code a bit, i think: void main(){ func((new C).toI2()); // compare with func(cast(I2)(new C)); C c = new C; func(c.toI1()); // compare with(cast(I1)c); } The calls to conversion methods could be even shorter if they were properties, because of omitted parens. Anyway, once I stuck to this strategy, it never failed me.
Jan 12 2011
parent %u <e ee.com> writes:
== Quote from Stanislav Blinov (blinov loniir.ru)'s article
 In C++ I sometimes have similar problems, especially with multiple
 inheritance. Though, as Jonathan mentioned, those problems are even more
 annoying because of hijacking: you don't always immediately notice them.
 Long ago I've decided to always employ conversion methods for such
 cases, which in D might look like this:
 class C : I2{
    I1 toI1() { return this; }
    I2 toI2() { return this; }
 }
 This unclutters the code a bit, i think:
 void main(){
    func((new C).toI2()); // compare with func(cast(I2)(new C));
    C c = new C;
    func(c.toI1()); // compare with(cast(I1)c);
 }
 The calls to conversion methods could be even shorter if they were
 properties, because of omitted parens. Anyway, once I stuck to this
 strategy, it never failed me.
I employ this strategy as well but I thought I would like to try the overload method, just to experiment :)
Jan 12 2011