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