My understanding is that OOPS rules dictate that if a virtual method is overridden in a child class then it must have the same number and type of arguments. But what if we are overriding in the child class with an argument type that is the child of the argument type used in the original parent class virtual definition?
Can a child class override a parent class virtual method with an argument type that is of the child type? is this allowed under polymorphism or is it illegal
See below an illustration of my question -
class parent;
virtual function void (parent p)
endfunction
endclass
class child extends parent;
function void (child c)
endfunction
endclass
This should be illegal in my opinion, because polymorphism works during the calling of the function. It works like a lookup table that determines the right function to invoke (i.e, either the parent’s function or the child’s function). The called function will try to deal with the arguments being passed (as is). This may require an implicit downcast or an implicit upcast of the argument depending on what is being passed. An automatic downcast (without the use of $cast function, may result in a crash.)
It is illegal. The base class prototype defines what types are legal to pass to the virtual method’s arguments, and how they are to be cast. If the extended class were to extend the type of its arguments, then that would allow illegal down casting.
A more detailed example that shows the problem:
module top;
class base;
virtual function void vf(base argument);
endfunction
endclass
class derived extends base;
int extra;
function void vf(derived argument); // illegal - type does not match
$display(argument.extra);
endfunction
endclass
base B = new;
derived D = new;
function void somef(base arg);
arg.vf(B); // illegal downcast B->argument
endfunction
initial somef(D); // upcast D->arg
endmodule
The problem here is that vf could be passed an object that is not have a derived type, and then the reference to argument.extra) would be fatal.
If you wanted to make this work, you would need to use a dynamic $cast
module top;
class base;
virtual function void vf(base argument);
endfunction
endclass
class derived extends base;
int extra;
function void vf(base argument);
derived e_arg;
if ($cast(e_arg, argument)) // must use $cast to test for legal downcasting
$display(e_arg.extra);
else
$display("not derived");
endfunction
endclass
base B = new;
derived D = new;
function void somef(base arg);
arg.vf(B);
arg.vf(D);
endfunction
initial somef(D); // upcast D->arg
endmodule