Hijacking
kris
fu at bar.org
Sun Aug 5 16:00:55 PDT 2007
Walter:
There's a related problem where a public method is added to a base-class
A (as in your example) but where the signature is *exactly* that of one
existing in derived class B. If A actually calls that new method
internally, "bad things"tm will almost certainly happen, since B never
intended to effectively override the newly-added method in A.
This is a very hard problem to isolate yet can be easily remedied by the
compiler. The request was first made two or three years back, and once
or twice since then: you make the "override" keyword *required*.
When "override" is required, the compiler can easily trap this related
type of hijacking and avoid such nasty surprises.
Walter Bright wrote:
> I want to continue a bit in the Overloading/Inheritance thread which is
> getting a little long, on a closely related issue which I find to be
> important, but so rarely referred to that I had to come up with a name
> for it - hijacking.
>
> Hijacking is when code A depends on B, and then when seemingly unrelated
> code C is modified, then A's behavior silently changes. Here's an
> example from C++:
>
> --A.h--
> void foo(long i);
>
> --B.c--
> #include "A.h"
> #include "C.h"
> ....
> foo(3); // calls A's foo(long)
> --------
>
> Let's say A.h and C.h are developed by different people. In C.h, the
> developer adds:
>
> --C.h--
> void foo(int i);
> -----
>
> This does something completely different from A.h's foo(long), because
> they just happened to share the same name. Now, when B.c is recompiled,
> it's call to foo is silently *hijacked* by C.h's foo.
>
> Because of C++'s overloading rules and lack of modularity, there's no
> way to programmatically defend against this. Instead, one has to rely on
> coding conventions (such as using a unique package prefix name on all
> symbols, like A_foo() and C_foo()).
>
> So how does this relate to the overloading/inheritance issues? Consider:
>
> ----A.d----
> class A
> {
> ...
> }
> -----B.d----
> import A;
> class B : A
> {
> void foo(long);
> }
> ....
> void bar(B b)
> {
> b.foo(3); // calls B.foo(long)
> }
> ----
>
> Let's say A.d comes from some third party library. Now the developer of
> A decides to add some functionality to class A, and adds the member
> function foo(int):
>
> ----A.d---
> class A
> {
> void foo(int);
> }
> ------------
>
> Now our hapless B programmer has his calls to B.foo(long) silently
> hijacked to A.foo(int) (under Java rules). I don't see any reasonable
> way for B to defend against this. Certainly, developer A doesn't have
> any idea who is deriving from A (and that's the point of polymorphism) -
> but should he be disallowed from adding *any* method names? And the
> hapless B developer, he wrote class B years ago and no longer quite
> remembers how it works, he just recompiles it and now it silently fails.
>
> So, this is one case where I feel C++ got it right, and Java didn't.
>
> (P.S. It's not a compiler implementation issue, nor is it a runtime
> performance issue.)
More information about the Digitalmars-d
mailing list