Overloading/Inheritance issue

Bruno Medeiros brunodomedeiros+spam at com.gmail
Fri Aug 3 15:17:22 PDT 2007


Regan, good thing posting about that other older thread, I didn't know 
about it, and it was nice to see some actual arguments for the current 
behavior (even if I don't agree with them, but at least they can be 
argued), instead of the typical "it's the way it's done in C++"/"it's 
how C++ people want it done"...

The first argument is this one:
http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=6975
(the one where with a series of cast, one can call a different method 
other than the "nearest" one in the method lineage hierarchy)
Indeed that's a problematic behavior, but it's not a language design 
error, it's a compiler bug! There has to be a way to make that work. 
Wasn't this option even considered or discussed? Did Walter just go 
right through to changing the language?


Regan Heath wrote:
> Steve Schveighoffer wrote:
> 
> Performance isn't the reason against the Java behaviour, here is Walters 
> explaination:
> 
> <quote Walter quoting Stroustrup>
> 
> Stroustrup gives two examples (slightly modified here):
> 
> ---------------------------------
> class X1 { void f(int); }
> 
> // chain of derivations X(n) : X(n-1)
> 
> class X9: X8 { void f(double); }
> 
> void g(X9 p)
> {
>     p.f(1);    // X1.f or X9.f ?
> }
> -----------------------------------
> His argument is that one can easilly miss an overload of f() somewhere in a
> complex class heirarchy, and argues that one should not need to understand
> everything about a class heirarchy in order to derive from it. 

The second argument. This one is simply crap...
Stroustrup argues "that one should not need to understand everything 
about a class heirarchy in order to derive from it". Well, maybe you 
don't have to understand *everything* but you surely will have to 
understand *a lot*, even if you aren't changing a lot of behavior in the 
subclass. This is simply something you can't (or shouldn't) escape from: 
if you are changing the implementation, even if just a bit, you have to 
understand the rest of implementation, or you risk breaking things, no 
mater how boring or worksome it might be. This is not the same as simply 
*using* a class, where you only have to understand it's 
interface/contract, and encapsulation shields you from the implementation.
This is my rebuttal for the general case of this argument, but as for 
that particular example, it should also be noted, that with a decent IDE 
(in the likeness of JDT), the example is totally moot. You just place 
your mouse of the function call, and a text hover will show you the 
signature (and javadoc) of the function, thus immediately indicating 
which overload is being called, without having to manually search N 
levels of hierarchy to find which overload it is. Code completion will 
also allow listing all available overloads in an equally easy and 
convenient way. This is yet another case of people failing to understand 
how semantic code analysis tools (ie, IDE) can influence language 
productivity and design shortcomings.
(Minor plug, these two features, especially the last one, are not too 
far from being implemented in the Descent project)

>The other
> example involves operator=(), but since D doesn't allow overloading
> operator=() instead I'll rewrite it as if it were a function that needs to
> alter a class state, and a derived class written later that 'caches' a
> computation on the derived state:
> 
> class B
> {    long x;
>      void set(long i) { x = i; }
>     void set(int i) { x = i; }
>     long squareIt() { return x * x; }
> }
> class D : B
> {
>     long square;
>     void set(long i) { B.set(i); square = x * x; }
>     long squareIt() { return square; }
> }
> 
> Now, imagine B were a complex class with a lot of stuff in it, and our
> optimizing programmer missed the existence of set(int). Then, one has:
> 
>     long foo(B b)
>     {
>         b.set(3);
>         return b.squareIt();
>     }
> 
> and we have an obscure bug.
> 
> </quote>
> 

The third and final argument. This one at least, I agree that it is a 
valid concern. However, this should be solved in another way, not with 
the current D behavior (which clearly breaks the is-a relationship, a 
fixture of OO semantics).
One suggestion I agree with, is that if a subclass does not override 
*all* overloads of the same function name, then it is a compiler error. 
Then the above code would simply be an error, forcing the user to use an 
alias to bring down the upper class overloads, or write their own overloads.
For example, I've personally written visitor classes that in D would 
*silently* break with this behavior, and it wouldn't be easy to spot it, 
as well as very error prone in the face of changes. I could post the 
examples but it likely wouldn't matter to Walter anyway.

PS: Someone call to this thread those guys who think D design 
development is "community-driven"... ;)

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



More information about the Digitalmars-d mailing list