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