Does re-declaration of a property in subclass affect virtual methods?

The following code is slightly modified from 8.14 Overridden members in IEEE Std 1800™-2017.

module tb;

  class Packet;
    integer i = 1;

    function integer get();
      get = i;
    endfunction

    virtual task set(int x);
      i=x;
    endtask
  endclass


  class LinkedPacket extends Packet;
    integer i = 2;

    function integer get();
      get = -i;
    endfunction

    virtual task set(int x);
      i=x*5;
    endtask

  endclass

  
  task set_print(Packet pkt);
    pkt.set(3);
    $display ("print pkt.i=%0d", pkt.i);
  endtask

  initial begin
	LinkedPacket lp = new;
	Packet p = lp;
    integer j;
	j = p.i; // j = 1, not 2
    $display ("j=p.i j=%0d", j);
	j = p.get(); // j = 1, not -1 or –2
    $display ("j=p.get() j=%0d", j);
    set_print(p);
  end
endmodule 

The print result is

j=p.i j=1
j=p.get() j=1
print pkt.i=1

But if I delete the line “integer i = 2;” in class LinkedPacket, then the print result is

j=p.i j=1
j=p.get() j=1
print pkt.i=15

I am wondering why “integer i = 2;” in class LinkedPacket affects the result of pkt.i.

Declaring a class property in an extended class with the same name as a property in a base class affects all methods in the extended class, regardless of whether they are virtual or not. Class inheritance is defined in such a way that a search for a class property starts in the local class first and then its super class, and then the next super class.

It’s usually a bad idea to give properties the same name in different levels of class inheritance. p.i and p.get both always refer to the same property in the base class Packet. But since the task set() is virtual, it calls the task defined in LinkedPacket and begins its search there. When i is defined in that class, the i defined in Packet is never set.

2 Likes

Thanks Dave for the answer.
But for the last sentence " When i is defined in that class, the i defined in Packet is never set."
I think you meant " When i is defined in LinkedPacket, the i defined in Packet is never set."
But from the result it looks like with i re-defined in LinkedPacket, the i defined in Packet is set to 1 which is set by the task set in the base class Packet.

The task set() in Packet never gets called. BTW this is denoted by Packet::set(). You constructed LinkedPacket and set() is virtual.

1 Like

Ah, I see.
I was wrong in the last reply, if Packet::set() had worked it should have printed “print pkt.i=3”.
I think it’s better to have linter to avoid re-declaration of properties in the subclasses to avoid confusion.
Thank you Dave.