www.digitalmars.com         C & C++   DMDScript  

D - [BUG]: promoting overloaded functions to subclass

reply Lars Ivar Igesund <larsivar igesund.net> writes:
class A {
   void foo() {}
}

class B : A {
   void foo(int i) {}
}

void main() {
   (new B).foo();
}

don't compile with the message
foo.d(10): function foo (int i) does not match argument types ()

It compiles fine if foo (int i) is moved to A.
So, if a method in a subclass has the same name as a method in the
super class, but with a different signature, the method from the
super class is lost. Since they are allowed to live together in the
same class, they should in parent and child classes.

Lars Ivar Igesund
Mar 31 2004
parent reply Manfred Nowak <svv1999 hotmail.com> writes:
Lars Ivar Igesund wrote:

 Since they are allowed to live together in the
 same class, they should in parent and child classes.

Not a bug. Overriding a function hides the overridden overloaded functions in the super class. Use an alias to import them. From C:\dmd\html\d\declaration.html: Aliases can also 'import' a set of overloaded functions, that can be overloaded with functions in the current scope: class A { int foo(int a) { return 1; } } class B : A { int foo( int a, uint b ) { return 2; } } class C : B { int foo( int a ) { return 3; } alias B.foo foo; } class D : C { } void test() { D b = new D(); int i; i = b.foo(1, 2u); // calls B.foo i = b.foo(1); // calls C.foo } So long!
Mar 31 2004
parent reply Lars Ivar Igesund <larsivar igesund.net> writes:
Manfred Nowak wrote:
 Lars Ivar Igesund wrote:
 
 
Since they are allowed to live together in the
same class, they should in parent and child classes.

Not a bug. Overriding a function hides the overridden overloaded functions in the super class. Use an alias to import them. From C:\dmd\html\d\declaration.html: Aliases can also 'import' a set of overloaded functions, that can be overloaded with functions in the current scope: class A { int foo(int a) { return 1; } } class B : A { int foo( int a, uint b ) { return 2; } } class C : B { int foo( int a ) { return 3; } alias B.foo foo; } class D : C { } void test() { D b = new D(); int i; i = b.foo(1, 2u); // calls B.foo i = b.foo(1); // calls C.foo } So long!

I admit that I expected D to function as Java in this regard. My opinion now is that D's spec has a bug. It should NOT be necessary to alias the super class' foo to be able to call it. IMO this defeats much of what makes OOP easy and elegant to use. Walter, please do it the obvious way. Lars Ivar Igesund
Mar 31 2004
next sibling parent Manfred Nowak <svv1999 hotmail.com> writes:
Lars Ivar Igesund wrote:

 Walter, please do it the obvious way.

Have a look at Ben's opinion on that. My opinion is, that the obvious way is already implemented. <btr852$2d1q$1 digitaldaemon.com> == D/21549 So long!
Mar 31 2004
prev sibling next sibling parent reply "Kris" <someidiot earthlink.dot.dot.dot.net> writes:
It's implemented the C++ way because apparently that's the target audience
for D (rather than Java, for example).

I find the approach totally non-intuitive, and contrary to the notion of
easy-to-learn (surely alias is considered a somewhat 'advanced' topic, if
not downright arcane?).

Personally, I think pandering to C++ history is the wrong approach. Walter
has already sidestepped a lot of the nonsense introduced by Bjarne-The-Toker
... this is one of the last vestiges, and needs some further excising.

- Kris



"Lars Ivar Igesund" <larsivar igesund.net> wrote in message
news:c4erto$278o$1 digitaldaemon.com...
 Manfred Nowak wrote:
 Lars Ivar Igesund wrote:


Since they are allowed to live together in the
same class, they should in parent and child classes.

Not a bug. Overriding a function hides the overridden overloaded


 in the super class. Use an alias to import them.

 From C:\dmd\html\d\declaration.html:

 Aliases can also 'import' a set of overloaded functions, that can be
 overloaded with functions in the current scope:
 class A {
     int foo(int a) { return 1; }
 }

 class B : A {
     int foo( int a, uint b ) { return 2; }
 }

 class C : B {
     int foo( int a ) { return 3; }
     alias B.foo foo;
 }

 class D : C  {
 }


 void test()
 {
     D b = new D();
     int i;

     i = b.foo(1, 2u); // calls B.foo
     i = b.foo(1); // calls C.foo
 }

 So long!

I admit that I expected D to function as Java in this regard. My opinion now is that D's spec has a bug. It should NOT be necessary to alias the super class' foo to be able to call it. IMO this defeats much of what makes OOP easy and elegant to use. Walter, please do it the obvious way. Lars Ivar Igesund

Mar 31 2004
next sibling parent Dave Sieber <dsieber spamnot.sbcglobal.net> writes:
"Kris" <someidiot earthlink.dot.dot.dot.net> wrote:

 It's implemented the C++ way because apparently that's the target
 audience for D (rather than Java, for example).

Nothing wrong with that in itself, since people in general don't want massive changes that require re-thinking from the beginning. D is as good as it now because a lot of what we know from C++ still applies. I was able to get a simple game working in a day or two (yes, after the usual newbie mistakes, but once solved I was "up and running").
 I find the approach totally non-intuitive, and contrary to the notion
 of easy-to-learn (surely alias is considered a somewhat 'advanced'
 topic, if not downright arcane?).

IMO, you shouldn't be forced to use alias (or anything else) for normal code. A language should work as expected by a typical user, which is one area where C++ falls on its face, and where D can outshine it. The Java approach is more sensible and workable in the real world -- of the two, I would almost always choose Java's way over C++ (where they are comparable). I suspect that this overload behavior may already be engrained in D, however.
 Personally, I think pandering to C++ history is the wrong approach.
 Walter has already sidestepped a lot of the nonsense introduced by
 Bjarne-The-Toker ... this is one of the last vestiges, and needs some
 further excising. 

I couldn't agree more. -- dave
Mar 31 2004
prev sibling parent reply John Reimer <jjreimer telus.net> writes:
Kris wrote:

 It's implemented the C++ way because apparently that's the target audience
 for D (rather than Java, for example).
 
 I find the approach totally non-intuitive, and contrary to the notion of
 easy-to-learn (surely alias is considered a somewhat 'advanced' topic, if
 not downright arcane?).
 
 Personally, I think pandering to C++ history is the wrong approach. Walter
 has already sidestepped a lot of the nonsense introduced by
 Bjarne-The-Toker ... this is one of the last vestiges, and needs some
 further excising.
 
 - Kris

The use of alias may be an ugly solution, I'll give it that. But I think the whole situation is ugly. In Java, it could be unclear which overloaded class is being called. In that respect,in D at least, the alias makes things much more clear about what's going on and what the programmer intends to do (unless the programmer using the class doesn't know that the alias exists -- that could confuse expected results). If you want to use a superclass method as the defualt, why was it overriden in the first place (other than adopting previous functionality in the subclass)? In solving these issues, it seems more important to design a project well in order to avoid such kludges. But, I guess, sometimes these things are unavoidable, in which case, explicit aliasing may be just barely excusable. Though, like I mentioned above, it still requires the programmer to know that a Java style overloading method is being simulated. If he/she doesn't know and only understands the D rules, aliasing could also be dangerous territory. But my experience in this is inadequate; so, as usual, I'm probably missing something. -John
Mar 31 2004
parent reply "Kris" <someidiot earthlink.dot.dot.dot.net> writes:
"John Reimer" wrote:
 <snip snip snip>
 But, I guess, sometimes these things are unavoidable, in which case,
 explicit aliasing may be just barely excusable.

I ran into this particular problem with Dsc.io, where various readers/writers overload a superclass method with another of the same basic name (put/get, opShl/opShr). Sometimes that sub-implementation changes the behavior of the super-method with the exact signature: for example, DisplayWriter prints a char[] in readable format, whereas Writer (binary version) emits the length first. Other times you just want to add a new signature with the same basic method name as the superclass already has (get/put etc...). For example: put(SomeClass sc) rather than the superclass put(int). Even after Walter showed me how to resolve this (and fixed a 0.81 bug), I still fail to grok the alias semantics coherently. Perhaps I'm not nearly as smart as I thought I was ... <g> - Kris
Mar 31 2004
parent reply John Reimer <jjreimer telus.net> writes:
 I ran into this particular problem with Dsc.io, where various
 readers/writers overload a superclass method with another of the same
 basic name (put/get, opShl/opShr).
 
 Sometimes that sub-implementation changes the behavior of the super-method
 with the exact signature: for example, DisplayWriter prints a char[] in
 readable format, whereas Writer (binary version) emits the length first.
 
 Other times you just want to add a new signature with the same basic
 method name as the superclass already has (get/put etc...). For example:
 put(SomeClass sc) rather than the superclass put(int).
 
 Even after Walter showed me how to resolve this (and fixed a 0.81 bug), I
 still fail to grok the alias semantics coherently. Perhaps I'm not nearly
 as smart as I thought I was ... <g>
 
  - Kris

Ok, I now see your points fairly clearly after looking over Dsc.io and your explanation. Apparently you have experienced the pain of this issue that I had not :-). If I'm correct, the system D uses is an all or nothing approach. You can't can't just merrily replace selected superclass methods in the subclass and expect the fallback superclass methods to work when called. You basically have to rewrite every method of the superclass in the subclass; for superclass calls you want to use, you have to explicitly call them (a la alias). This does make the D way quite tedious. I guess I can see how a lazy java methodology might attract people ;-). It's amazing confusing these issues can be... Later, John
Apr 01 2004
parent reply Ben Hinkle <bhinkle4 juno.com> writes:
On Thu, 01 Apr 2004 21:52:10 -0800, John Reimer <jjreimer telus.net>
wrote:

 I ran into this particular problem with Dsc.io, where various
 readers/writers overload a superclass method with another of the same
 basic name (put/get, opShl/opShr).
 
 Sometimes that sub-implementation changes the behavior of the super-method
 with the exact signature: for example, DisplayWriter prints a char[] in
 readable format, whereas Writer (binary version) emits the length first.
 
 Other times you just want to add a new signature with the same basic
 method name as the superclass already has (get/put etc...). For example:
 put(SomeClass sc) rather than the superclass put(int).
 
 Even after Walter showed me how to resolve this (and fixed a 0.81 bug), I
 still fail to grok the alias semantics coherently. Perhaps I'm not nearly
 as smart as I thought I was ... <g>
 
  - Kris

Ok, I now see your points fairly clearly after looking over Dsc.io and your explanation. Apparently you have experienced the pain of this issue that I had not :-). If I'm correct, the system D uses is an all or nothing approach. You can't can't just merrily replace selected superclass methods in the subclass and expect the fallback superclass methods to work when called. You basically have to rewrite every method of the superclass in the subclass; for superclass calls you want to use, you have to explicitly call them (a la alias). This does make the D way quite tedious. I guess I can see how a lazy java methodology might attract people ;-).

My rule of thumb is to use alias when I want to overload something from another class or module. You can suck in all the methods you want just using one or two alias lines. For example: class A { void bar(double x){printf("in A\n");} void bar(char[] x){printf("in A: %.*s\n",x);} } class B:A { alias A.bar bar; void bar(int x){printf("in B\n");} } int main() { B a=new B(); a.bar(1); a.bar(1.0); a.bar("hello"); return 0; } Alias is your friend :-)
It's amazing confusing these issues can be...

Later,

John

Apr 02 2004
next sibling parent John Reimer <jjreimer telus.net> writes:
Ben Hinkle wrote:

 
 My rule of thumb is to use alias when I want to overload something
 from another class or module. You can suck in all the methods you
 want just using one or two alias lines. For example:
 
 class A
 {
     void bar(double x){printf("in A\n");}
     void bar(char[] x){printf("in A: %.*s\n",x);}
 }
 class B:A
 {
     alias A.bar bar;
     void bar(int x){printf("in B\n");}
 }
 
 int
 main()
 {
     B a=new B();
     a.bar(1);
     a.bar(1.0);
     a.bar("hello");
     return 0;
 }
 
 
 Alias is your friend :-)
 

Ah ha! I do see it now. Thanks!
Apr 02 2004
prev sibling parent Manfred Nowak <svv1999 hotmail.com> writes:
Ben Hinkle wrote:

[...]
 Alias is your friend :-)

Agreed. However, it can become tedious to provide an alias for every function, that I want to overload that way. D already has syntactic sugar in several cases. For example the static attribute for a single declaration can be extended by prepending it to a block of declarations or all of the following declarations, except overridden by another attribute. So long!
Apr 02 2004
prev sibling parent reply Brad Anderson <brad dsource.dot.org> writes:
Lars Ivar Igesund wrote:
 I admit that I expected D to function as Java in this regard.
 My opinion now is that D's spec has a bug. It should NOT be
 necessary to alias the super class' foo to be able to call it.

Ouch, I must have missed Ben's post earlier about this. It will make the port of SWT --> DWT a real pain in the ass. I was also (incorrectly) assuming that you could overload away. I'll have to agree with the rest of the thread that, even though it doesn't phase the C++ people, Java may have a more intuitive solution here. Besides, D will not only win over a lot of C++'ers. 3 million Java programmers are going to look at D and think "Wow, I can compile it? Sweet!" BA
Mar 31 2004
parent reply Brad Anderson <brad dsource.dot.org> writes:
Sorry about the self-post...

Brad Anderson wrote:
 3 million Java programmers are going to look at D and think "Wow, I can
compile 
 it?  Sweet!"

Okay, maybe not all 3 million will look, but hopefully a lot. And I meant 'compile it natively' BA
Mar 31 2004
parent reply John Reimer <jjreimer telus.net> writes:
 
 
 Okay, maybe not all 3 million will look, but hopefully a lot.  And I 
 meant 'compile it natively'
 
 BA

Well, I'm expecting there's going to be a lot of hidden problems that will need to fixed once the compile/link phase is complete. I don't know how this particular issue will affect the SWT port; I'm thinking that when class methods are called with the correct number of arguments, the intuitive meaning is that the most recent subclass method (of the same name) is going to be called. It's more clear to use an explicit method reference anyway. It could get confusing otherwise which method is being called. I don't know; I just think it's better to have to call b.foo() explicitly from class C if there's functionality you need from the superclass. At least people examining the code know exactly what's going on. I guess if SWT does make use of overloaded methods this way, it could be tricky to catch it and make the appropriate D conversion. But then the D code will be more readable than the Java code when it's done :-).
Mar 31 2004
parent reply Manfred Nowak <svv1999 hotmail.com> writes:
John Reimer wrote:

[...]
 But then the D code will be more readable than the Java code when it's
 done :-).

I totally agree with you. There was just a discussion about sequenced default valued parameters. One argument was, that the coder must simply not be aware of them, when coding. This argument holds here in the other way round: a coder might just not be aware of the fact, that he overrides a member with the same name of the superclass, because he is simply not aware of the fact, that there is one. Then providing the function call with a wrong typed argument, which causes no error, because there is a matching function in the superclass, may result in a desaster. By explicitely importing the overloaded functions the coder states, that he knows of them and wants to extend their functionality. On the other hand the current implementation provides a mechanism to block unwanted functionality. How could this achieved by a java like approach? So long!
Mar 31 2004
parent reply "Kris" <someidiot earthlink.dot.dot.dot.net> writes:
Perhaps some syntactic sugar would make this pill more palatable?

For example, one might apply the overrides keyword to the superclass like
so:

class Foo : overrides Bar
{
}

That's truly explicit, easy to learn, easy to spot and, importantly, easy
for an IDE to do something constructive with (no pun intended). The alias
stuff is black-magic in comparison, and IDE's will have a much harder time
grokking them (if they even bother).

Even better, this would be simple for Walter to add, since it's just an
alias for a specific and common usage of alias :-)

IMHO, this is one of those things that can make a language much easier to
grasp, and more consistent in its usage. That's really important in any
quest to gain mass adoption.

- Kris


"Manfred Nowak" <svv1999 hotmail.com> wrote in message
news:c4feg9$34o$1 digitaldaemon.com...
 John Reimer wrote:

 [...]
 But then the D code will be more readable than the Java code when it's
 done :-).

I totally agree with you. There was just a discussion about sequenced default valued parameters. One argument was, that the coder must simply not be aware of them, when coding. This argument holds here in the other way round: a coder might just not be aware of the fact, that he overrides a member with the same name of the superclass, because he is simply not aware of the fact, that there is one. Then providing the function call with a wrong typed argument, which causes no error, because there is a matching function in the superclass, may result in a desaster. By explicitely importing the overloaded functions the coder states, that he knows of them and wants to extend their functionality. On the other hand the current implementation provides a mechanism to block unwanted functionality. How could this achieved by a java like approach? So long!

Mar 31 2004
next sibling parent John Reimer <jjreimer telus.net> writes:
Kris wrote:

 Perhaps some syntactic sugar would make this pill more palatable?
 
 For example, one might apply the overrides keyword to the superclass like
 so:
 
 class Foo : overrides Bar
 {
 }
 
 That's truly explicit, easy to learn, easy to spot and, importantly, easy
 for an IDE to do something constructive with (no pun intended). The alias
 stuff is black-magic in comparison, and IDE's will have a much harder time
 grokking them (if they even bother).
 
 Even better, this would be simple for Walter to add, since it's just an
 alias for a specific and common usage of alias :-)
 
 IMHO, this is one of those things that can make a language much easier to
 grasp, and more consistent in its usage. That's really important in any
 quest to gain mass adoption.
 
 - Kris
 

Very true. Something cleaner then alias, yet explicit would be desirable.
Mar 31 2004
prev sibling parent reply Manfred Nowak <svv1999 hotmail.com> writes:
Kris wrote:

 Perhaps some syntactic sugar would make this pill more palatable?

That is not sugar. As far as I understand you, both ways should be incorporated into D. Because the code must state that it is inherent dangerous, I would not priliminary exclude your suggestion. So long!
Mar 31 2004
parent reply "Kris" <someidiot earthlink.dot.dot.dot.net> writes:
Why, thank you Manfred <g>

You understood me correctly: this would be the "non-expert" version of alias
usage, as applied to superclass method-overloading. Alias would still exist
in its full glory, to do everything it currently does.

- Kris

"Manfred Nowak" <svv1999 hotmail.com> wrote in message
news:c4fq3f$l9b$1 digitaldaemon.com...
 Kris wrote:

 Perhaps some syntactic sugar would make this pill more palatable?

That is not sugar. As far as I understand you, both ways should be incorporated into D. Because the code must state that it is inherent dangerous, I would not priliminary exclude your suggestion. So long!

Mar 31 2004
parent Manfred Nowak <svv1999 hotmail.com> writes:
Kris wrote:

[...]
 this would be the "non-expert" version of alias usage

Now only the proof does not exist, that both paradigmas can coexist. So long!
Apr 02 2004