Thread overview
how to fix such a hijacking problem in D ?
Dec 16, 2007
z_axis
Dec 16, 2007
Bill Baxter
Dec 16, 2007
Bill Baxter
Dec 18, 2007
z_axis
December 16, 2007
import std.stdio;

class A
{
    void foo(long) {}
    void def() { writefln("A.def()"); foo(1L); }  // expects to call A.foo(long)
}

class B : A
{
    void foo(long) { writefln("B.foo()"); };	// will hijack A's foo()
}

void abc(B b)
{	
    b.def();
}


void main(char[][] args)
{	
   abc(new B);
}
output:
A.def()
B.foo()

The B will hijack the A's foo(long) ?!

any suggestion ?
December 16, 2007
z_axis wrote:
> import std.stdio;
> 
> class A
> {
>     void foo(long) {}
>     void def() { writefln("A.def()"); foo(1L); }  // expects to call A.foo(long)
> }
> 
> class B : A
> {
>     void foo(long) { writefln("B.foo()"); };    // will hijack A's foo()
> }
> 
> void abc(B b)
> {       b.def();
> }
> 
> 
> void main(char[][] args)
> {      abc(new B);
> }
> output:
> A.def()
> B.foo()
> 
> The B will hijack the A's foo(long) ?!
> 
> any suggestion ?


I think "final" is for that.  Says that the method should not be virtual (virtual is the default in D).

   final void foo(long) {...}

Not sure if that works, since it's actually not documented as far as I can tell.  But DFL uses 'final' a lot so I'd guess it does something. Or else DFL is just deluding itself.

Another option would be to rename them per-class, or use "static" if you don't actually need the 'this' pointer.

--bb
December 16, 2007
Bill Baxter wrote:
> z_axis wrote:
>> import std.stdio;
>>
>> class A
>> {
>>     void foo(long) {}
>>     void def() { writefln("A.def()"); foo(1L); }  // expects to call A.foo(long)
>> }
>>
>> class B : A
>> {
>>     void foo(long) { writefln("B.foo()"); };    // will hijack A's foo()
>> }
>>
>> void abc(B b)
>> {       b.def();
>> }
>>
>>
>> void main(char[][] args)
>> {      abc(new B);
>> }
>> output:
>> A.def()
>> B.foo()
>>
>> The B will hijack the A's foo(long) ?!
>>
>> any suggestion ?
> 
> 
> I think "final" is for that.  Says that the method should not be virtual (virtual is the default in D).
> 
>    final void foo(long) {...}
> 
> Not sure if that works, since it's actually not documented as far as I can tell.  But DFL uses 'final' a lot so I'd guess it does something. Or else DFL is just deluding itself.
> 
> Another option would be to rename them per-class, or use "static" if you don't actually need the 'this' pointer.

Another option would be to make foo(long) a template, since those can't be virtual.

   void foo()(long) {}

--bb
December 16, 2007
"z_axis" <z_axis@163.com> wrote in message news:op.t3fe7a2l1uofcn@sw2wolf...
> import std.stdio;
>
> class A
> {
>     void foo(long) {}
>     void def() { writefln("A.def()"); foo(1L); }  // expects to call
> A.foo(long)
> }

Another way to solve this (Bill's will probably work too) is to make the call to foo non-virtual.

void def()
{
    writefln("A.def()");
    typeof(this).foo(1L); // performs non-virtual call
}

This way foo can still be virtual and overridden, but the call will always call A's implementation of foo.


December 18, 2007
thanks for all your answer !
i really donot understand the following sentences from http://www.digitalmars.com/d/hijack.html

The D solution is straightforward. If a function in a derived class overrides a function in a base class, it must
use the storage class override. If it overrides without using the override storage class it's an error.
If it uses the override storage class without overriding anything, it's an error.

regards!
December 18, 2007
"z_axis" <z_axis@163.com> wrote in message news:op.t3i7wpdc1uofcn@sw2wolf...
> thanks for all your answer !
> i really donot understand the following sentences from
> http://www.digitalmars.com/d/hijack.html
>
> The D solution is straightforward. If a function in a derived class
> overrides a function in a base class, it must
> use the storage class override. If it overrides without using the override
> storage class it's an error.
> If it uses the override storage class without overriding anything, it's an
> error.
>
> regards!

It means that your code would give an error if you used D2.  In D1, 'override' is optional, but in D2 it's been made mandatory.

Regardless even if you put 'override' on the subclass's "foo", it wouldn't help with your problem; you either have to make a non-virtual call or make "foo" final.