Proposition for change in D regarding Inheriting overloaded methods

Tiago Carvalho merlin3000 at portugalmail.pt
Tue Aug 7 12:13:05 PDT 2007


Walter Bright Wrote:

> Steven Schveighoffer wrote:
> > However, does the author intend to handle the case where foo(int) is called? 
> > Let's assume he does (which is what the current compiler assumes).  The 
> > author has not forbidden the user of the class from calling A.foo, because 
> > the user can simply cast to an A object, and call A.foo(int) directly. 
> > Therefore, if the author meant to override foo(int) by defining just a 
> > foo(long), he has failed.  From these points, I believe that the above code 
> > is an example of an incorrectly implemented override, and I believe that the 
> > correct response the compiler should have is to error out, not while 
> > compiling test(), but while compiling B, indicating to the user that he 
> > should either declare the alias, or override foo(int).  This is the point in 
> > which my solution differs from Java.  Java would allow this to proceed, and 
> > call the base class' foo(int) in all cases, which is not what the author 
> > intended.
> 
> The next update of the compiler will throw a runtime exception for this 
> case.
> 
> > The second issue is how to handle the foo(char[]) case.  In the current 
> > implementation, because A is not searched for overrides, the compiler 
> > produces an error indicating that the user tried to call the foo(long) 
> > method, but there is no implicit conversion from char[] to long.  There are 
> > two possibilities.  One is that the author did not notice that A.foo(char[]) 
> > existed, and intended to override all instances of foo() with his foo(long) 
> > override.  However, the author is NOT notified of this issue, only the user 
> > of the class is notified of this issue.  So the potential for unambiguous 
> > code to have escaped exists.
> 
> But a compile time error is still generated, so I don't regard this as a 
> big problem. The big problems are silent hijacking of code.
> 
> 
> > The second possibility is that the author 
> > fully intended to allow the base class to define foo(char[]), but forgot to 
> > define the alias.  Again, since the compiler gives no error, he is unaware 
> > that he is releasing buggy code to the world.  I believe the correct 
> > assumption of the compiler should be that the user wanted the alias for the 
> > base class' foo(char[]), and should alias it implicitly if and only if no 
> > suitable match exists on the derived class.  In the case where the author 
> > did not notice foo(char[]) existed, he problably doesn't mind that 
> > foo(char[]) is defined by the base class.
> 
> The problem with code that looks like a mistake, but the compiler makes 
> some assumption about it and compiles it anyway, is that the code 
> auditor cannot tell if it was intended behavior or a coding error. 
> Here's a simple example:
> 
> void foo()
> { int i;
>    ...
>    { int i;
>      ...
>      use i for something;
>    }
> }
> 
> To a code auditor, that shadowing declaration of i looks like a mistake, 
> because possibly the "use i for something" code was meant to refer to 
> the outer i, not the inner one. (This can happen when code gets updated 
> by multiple people.) To determine if it was an actual mistake, the code 
> auditor is in for some serious spelunking. This is why, in D, shadowing 
> declarations are illegal. It makes life easier for the auditor, because 
> code that looks like a mistake is not allowed.
> 
> > If a suitable match exists that 
> > is not a direct override of the base class, then the issue reduces to the 
> > previous case, where an implicit conversion is required, and the compiler 
> > should error out.
> > 
> > There is one other possibile solution that I would be willing to concede to, 
> > and that is that the compiler errors out if the base class does not override 
> > all overloads of a particular method name.  This forces the user to either 
> > override all overloads of the method, or define the alias.  This would be 
> > the safest solution, as the author of B must make his intentions perfectly 
> > clear.
> 
> I am not comfortable with this method, as it will force the derived 
> class programmer to implement overloads that may not be at all meant to 
> exist in the API he defines for that class. I think he should be in full 
> control of the API for the class, and not forced to provide 
> implementations of functions that may be irrelevant clutter. I prefer 
> the solution where attempts to call unoverridden base class overloads 
> will result in a runtime exception.
> 
> > I believe this will give us the best of both camps, and allow much less code 
> > to be released with silent bugs than the current implementation.
> 
> I believe that the enforcing of the override attribute, and the runtime 
> exception case as described, closes all the known hijacking issues.

For the first example I think the exception solution will work fine. Since any predefined choice could hurt the work of the programmer.

For the second, where the argument can't be implicitily converted, I think that if the object in question doesn't have the required method, that method should be looked in the base classes, until it reaches the Object class. And it should do this without needing to declare an alias.

I think this is similar to how java works. And it's also similar to Regan sugestion.



More information about the Digitalmars-d mailing list