polymorphism: overloading vs. overriding

Bruno Medeiros brunodomedeirosATgmail at SPAM.com
Sun May 7 03:51:49 PDT 2006


Markus Kranz wrote:
> Following the rule of last surprise: wouldn't it be desirable if the output of
> the following program would be:
> 
> Bar.doIt()
> Bar.doIt(Bar)
> 
> The actual output
> 
> Bar.doIt()
> Foo.doIt(Foo)
> 
> at least for me is a little bit surprising since the best matching function
> seems to be Bar.doIt(Bar).
> As overriding with covariant return types is supported it seems a bit unnatural
> to me that overriding with covariant arguments does not work.
> 
> Instead of doing overload resolution before virtual function resolution (what
> seems to be done now) an implementation of 'covariant arguments' theoretically
> could be as simple as reversing the order of resolution.
> 
> What do you think?
> 
> Regards,
> Markus
> 
> --
> import std.stdio;
> 
> class Foo {
> void doIt() { writefln("Foo.doIt()"); }
> void doIt(Foo that) { writefln("Foo.doIt(Foo)"); }
> }
> 
> class Bar : Foo {
> //overrides Foo.doIt()
> void doIt() { writefln("Bar.doIt()"); }
> 
> //overloads (inherited) Foo.doIt(Foo)
> void doIt(Bar that) { writefln("Bar.doIt(Bar)"); }
> }
> 
> int main() {
> Foo foo = new Bar();
> 
> foo.doIt();
> foo.doIt(foo);
> }
> 
> 

No, it's not unnatural. For a function to override another, the return 
type must be covariant, but the parameters must be contravariant.
It's quite natural to be this way, in fact, it's the only correct way 
(other than invariant parameters).
The reason why it is so, is because for a function to override another, 
it must handle all (or more) inputs than the previous function.
Consider, in your example, the following addition

   class Baz : Foo { }

Foo.doIt(Foo that) can handle an argument of type Baz, but
Bar.doIt(Bar that) cannot handle such an argument. Thus Bar.doIt doesn't 
override Foo.doIt

-- 
Bruno Medeiros - CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D



More information about the Digitalmars-d mailing list