www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - how to fix such a hijacking problem in D ?

reply z_axis <z_axis 163.com> writes:
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 ?
Dec 16 2007
next sibling parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
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
Dec 16 2007
parent Bill Baxter <dnewsgroup billbaxter.com> writes:
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
Dec 16 2007
prev sibling next sibling parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"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.
Dec 16 2007
prev sibling parent reply z_axis <z_axis 163.com> writes:
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!
Dec 18 2007
parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"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.
Dec 18 2007