Virtual method prototype definition in child class

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

Is this valid?

Thanks

In reply to ashok2469:

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.)

In reply to ashok2469:

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

In reply to dave_59:

Thanks for your response. I see the issue you are describing.

So the issue ultimately arises due to function calls being unable to do some kind of implicit downcast correct?