Abstract methods, interface class, and virtual methods

I have, what I think is a basic question, but believe I’m missing something obvious.
We use a interface classes a lot in our design to abstract our models and classes. However, I’ve been experimenting with how we are doing things to reduce some of our repetition in coding.

I notice in the definition for Virtual methods, a functions return type shall be one of:

  • a matching type
  • or a derived class type
    of the defined virtual function type in the superclass.

Does this apply to interface classes as well? An example:

module tb;

  interface class base_ic;
    pure virtual function base_ic copy(); // does deep copy
  endclass

  class foo_c implements base_ic;
    bit foo;

    function foo_c copy();
      foo_c cpy;
      cpy = new this;
      return( cpy );
    endfunction       
  endclass
 
endmodule

This reports an error - the concrete class “foo_c” implementation of copy() does not explicitly match the return type of the superclass - it’s the implemented class (not explicitly DERIVED class as the standard states). But my gut says this should work, and would make coding for polymorphic techniques MUCH easier if it did work.

I’m forced to something like:

module tb;

  interface class base_ic;
    pure virtual function base_ic copy(); // does deep copy
  endclass

  class foo_c implements base_ic;
    bit foo;
    function foo_c my_copy();
      foo_c cpy;
      cpy = new this;
      return( cpy );
    endfunction       
    
    virtual function base_ic copy(); 
      return( this.my_copy() );
    endfunction

  endclass
endmodule

While not terribly difficult, this starts getting messy with multiple derived classes (I need to start coding an explicitly named my_copy() for each derived class).

Am I missing something obvious?

Thanks,

Mark

In reply to Mark Curry:

First, SystemVerilog does not support method overloading.

Second, even in languages like C++, this wouldn’t work, as type signatures must match when overriding or you end up creating a different method ( via overloading ).

Your particular example implies an implicit cast from base_ic to foo_c. You’d need a dynamically typed language to do that.

First, SystemVerilog does not support method overloading.

Huh? Derived classes can overload methods of the parent class.
To be fair - I don’t know C++, and I may have the terminology wrong…

Your particular example implies an implicit cast from base_ic to foo_c. You’d need a dynamically typed language to do that.

foo_c is an implementation of base_ic. The standard indicates this is ok with virtual methods and abstract classes, but isn’t clear in the case of interface class. I don’t think it’s strictly a derived class, hence the error - but would certainly be much more convenient it it worked.

Regards,
Mark

In reply to Mark Curry:

I tried your example and it didn’t compile initially. I got a ‘does not implement method in interface error’. I changed it up a bit by explicitly declaring the class function as ‘virtual’:


class foo_c implements base_ic;
  bit foo;

  virtual function foo_c copy();
    // ...
  endfunction

endclass

This way it worked.

The error message I initially got is different that what you were getting, so I guess we’re using different tools. Since this is allowed for regular classes, you would expect this to work with interface classes as well, right? I assume this is the intention (since Java provides the same mechanism), but the tool vendors tend to have their own interpretations.

Note: returning a more specific type from a function is called a covariant return type.

In reply to Tudor Timi:

Tudor,

Thanks for the reply - I did miss the virtual tag on my example. Here’s my corrected full example:

module tb;
  interface class base_ic;
    pure virtual function base_ic copy(); // does deep copy
  endclass

  class foo_c implements base_ic;
    bit foo;

    virtual function foo_c copy();
      foo_c cpy;
      cpy = new this;
      return( cpy );
    endfunction       
  endclass
 endmodule

This fails with my simulator. Sounds like this works for you and you believe it’s legal SystemVerilog - Looks like I may need to pursue this problem with my simulation vendor.

To be clear, here’s the same example coded up to use just pure virtual classes as the abstraction mechanism, instead of interface classes:

module tb;
  virtual class base_ic;
    pure virtual function base_ic copy(); // does deep copy
  endclass

  class foo_c extends base_ic;
    bit foo;

    virtual function foo_c copy();
      foo_c cpy;
      cpy = new this;
      return( cpy );
    endfunction       
  endclass
 endmodule

You’ll note, the covariant return type (thanks for the terminology!) in the concrete class method.

This second example works in my simulator. The first doesn’t.

Regards,
Mark

In reply to Mark Curry:

Huh? Derived classes can overload methods of the parent class.
To be fair - I don’t know C++, and I may have the terminology wrong…

In reply to Tudor Timi:

Note: returning a more specific type from a function is called a covariant return type.

I didn’t realize the SV LRM allowed that, but Tudor is correct. Thanks for the correction!
P1800-2012, Chapter 8.20

The return type of a virtual function shall be either:
— a matching type (see 6.22.1)
— or a derived class type

Difference between method Overloading and Overriding

Thanks for the pointer - I’ll strive to improve my use of the correct terminology. SystemVerilog allows method override, (not overload). This thread is discussing SV support of a covariant return type of a method, which we’ve shown is supported by the SV standard. (But perhaps not all tools).