Thread overview
bug: method override via overload
Feb 20, 2006
pragma
Feb 20, 2006
Nick
Feb 21, 2006
Ant
Feb 21, 2006
pragma
Feb 23, 2006
Nick
Feb 23, 2006
pragma
Feb 21, 2006
Nick
February 20, 2006
Apologies if this has been posted before:

The compiler seems to accept the method overload for 'bar' with a different type of argument, yet it fails to resolve the correct overload when that method is called.  Near as I can tell, since both int and Foo are technically the same type, the base class method is being completly overriden - is this a type covariance issue?

One can change the return type of the overriden method to match the overriding one, suggesting that the compiler wants to treat both methods as distinct (it doesn't complain that they match).  Perhaps Typedef is to blame here?

# typedef int Foo;
#
# class Gorf{
# 	public void bar(int x){} // return type here is immaterial (try 'int')
# }
#
# class Goat : Gorf{
# 	public int bar(Foo x){}
# }
#
# void main(){
# 	Foo y = 0;
# 	int z = 0;
# 	Goat g = new Goat();
# 	g.bar(y); // works
# 	g.bar(z); // fails
# }


- Eric Anderton at yahoo
February 20, 2006
In article <dtcoqg$22lv$1@digitaldaemon.com>, pragma says...
>
># typedef int Foo;
>#
># class Gorf{
># 	public void bar(int x){} // return type here is immaterial (try 'int')
># }
>#
># class Goat : Gorf{
># 	public int bar(Foo x){}
># }
>#
># void main(){
># 	Foo y = 0;
># 	int z = 0;
># 	Goat g = new Goat();
># 	g.bar(y); // works
># 	g.bar(z); // fails
># }

This is by design, not a bug. When you introduce members with the same name in a child class, you automatically hide the inherited name from the parent. There are good reasons to do this, and C++ does it the same way. Add the line

alias Gorf.bar bar;

to Goat to get it the way you want. (BTW this question comes up a lot - perhaps it's time to make a FAQ for these groups?)

Nick


February 21, 2006
Oops, I missed the typedef at the begining of your example. I must have answered on auto pilot there, sorry.

Still, I think the current behavior is correct. Even though Foo and int are 'nearly' the same type, they are not _actually_ the same type, so this is a result of having strong typedefs in D. I guess int and Foo are treated much like eg. float and double in this case, implicitly convertable but different types.

Nick


February 21, 2006
In article <dtcpkd$23ii$1@digitaldaemon.com>, Nick says...
>
>In article <dtcoqg$22lv$1@digitaldaemon.com>, pragma says...
>>
>># typedef int Foo;
>>#
>># class Gorf{
>># 	public void bar(int x){} // return type here is immaterial (try 'int')
>># }
>>#
>># class Goat : Gorf{
>># 	public int bar(Foo x){}
>># }
>>#
>># void main(){
>># 	Foo y = 0;
>># 	int z = 0;
>># 	Goat g = new Goat();
>># 	g.bar(y); // works
>># 	g.bar(z); // fails
>># }
>
>This is by design, not a bug. When you introduce members with the same name in a child class, you automatically hide the inherited name from the parent. There are good reasons to do this

Where are those?
I try to look for them but only found the ones from Bjarne and Bright...

Ant


February 21, 2006
In article <dtf9t2$1vjk$1@digitaldaemon.com>, Ant says...
>
>In article <dtcpkd$23ii$1@digitaldaemon.com>, Nick says...
>>
>>In article <dtcoqg$22lv$1@digitaldaemon.com>, pragma says...
>>>
>>># typedef int Foo;
>>>#
>>># class Gorf{
>>># 	public void bar(int x){} // return type here is immaterial (try 'int')
>>># }
>>>#
>>># class Goat : Gorf{
>>># 	public int bar(Foo x){}
>>># }
>>>#
>>># void main(){
>>># 	Foo y = 0;
>>># 	int z = 0;
>>># 	Goat g = new Goat();
>>># 	g.bar(y); // works
>>># 	g.bar(z); // fails
>>># }
>>
>>This is by design, not a bug. When you introduce members with the same name in a child class, you automatically hide the inherited name from the parent. There are good reasons to do this
>
>Where are those?

Exactly what I'm trying to figure out. ;)

BTW, thank you Nick: your suggested workaround via 'alias' worked great.

Anyway, my main problem with this behavior is that if Foo were a class, the code in main() would compile and behave just fine.  So why such an inconsistency could be tolerated, is beyond me.

Also the docs say (for the most part) that this shouldn't happen:

"Strong types can be introduced with the typedef. Strong types are semantically a distinct type to the type checking system, for function overloading, and for the debugger."

# typedef int myint;
#
# void foo(int x) {  }
# void foo(myint m) {  }
#
# myint b;
# foo(b);	        // calls foo(myint)

So it works fine with overloads in the same scope, but fails when typedefs overlap with inherited methods that posess the same underlying type.  That smells like a bug to me.

- Eric Anderton at yahoo
February 23, 2006
In article <dtg3cl$2ru6$1@digitaldaemon.com>, pragma says...
>
>Anyway, my main problem with this behavior is that if Foo were a class, the code in main() would compile and behave just fine.  So why such an inconsistency could be tolerated, is beyond me.

Well actually it doesn't work, it behaves the same way. Try it :)

Unlike many quirks from C++, Walter opted to keep this one. I'm not really sure either way if it is good or bad, though. Perhaps it would be good to change it since so many people find it counter-intuitive. I guess I've just gotten used to it from C++.

Nick


February 23, 2006
In article <dtjp93$1lra$1@digitaldaemon.com>, Nick says...
>
>In article <dtg3cl$2ru6$1@digitaldaemon.com>, pragma says...
>>
>>Anyway, my main problem with this behavior is that if Foo were a class, the code in main() would compile and behave just fine.  So why such an inconsistency could be tolerated, is beyond me.
>
>Well actually it doesn't work, it behaves the same way. Try it :)
>
>Unlike many quirks from C++, Walter opted to keep this one. I'm not really sure either way if it is good or bad, though. Perhaps it would be good to change it since so many people find it counter-intuitive. I guess I've just gotten used to it from C++.

I stand corrected.  Thank you for the lively discussion, and setting me straight! :)
>Nick
>
>

- Eric Anderton