Hijacking

Kristian Kilpi kjkilpi at gmail.com
Fri Aug 10 12:34:32 PDT 2007


The old aliasing trick will still cause problems.

(The 'override' keyword won't solve the problem in the following case.)

   class A {
     void foo(int);
     void foo(long);
   }

   class B : A {
     alias A.foo foo;
     override void foo(int);
   }

   void bar(B b) {
     short val = 1;

     b.foo(val);  //calls 'foo(int)'
   }

Now 'foo(short)' is added to 'A':

   void bar(B b) {
     short val = 1;

     b.foo(val);  //calls 'foo(short)'
   }


Solutions:

(1) The aliasing trick will be banned (argh).

or

(2) One can overload final functions only (ermmm).

Or, to solve the hijacking problem once and for all:

(3) No implicit type casting with function calls.

Somehow (3) seems appealing (but I'm probably just too tired).
I go to sleep now... ;)




On Sun, 05 Aug 2007 21:47:18 +0300, Walter Bright  
<newshound1 at digitalmars.com> 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