Regarding parameterized class

Hi,
I have below two pieces of code. In the first one, when I do upcasting, there is runtime error. I assume it is because of incompatible types of class param.

In the second code, the upcasting works fine. Can someone explain the difference?
I know the examples are two different things, in the second code I am making param_e parameterized and it is using default parameters of param. But isnt it still changing type of variable a. I was looking for more explanation so concept is registered properly to me.

PS: I have already gone through parameterized and inheritance concept.

first code

class param#(type T=int);
  T a;
endclass

class param_e extends param#(bit);
endclass

class param_f extends param#(real);
endclass

module top;
  
  param p;
  param_e pe;
  param_f pf;
  
  initial begin
    //p = new();
    pe = new();
    pf = new();
    pe.a = 1;
    p = pe;
    pf.a = 10;
    $display("p.a: %0d", p.a);
    $display("pe.a: %0d", pe.a);
    $display("pf.a: %0d", pf.a);
  end
endmodule

error: # ** Fatal: Illegal assignment to class work.testbench_sv_unit::param #(int) from class work.testbench_sv_unit::param_e

Time: 0 ns Iteration: 0 Process: /top/#INITIAL#23 File: testbench.sv

Fatal error at testbench.sv line 26

Second code

class param#(type T=int);
  
  T a;
  
endclass

class param_e#(type T=bit) extends param;
  
endclass

class param_f extends param#(real);
  
endclass

module top;
  
  param p;
  param_e pe;
  param_f pf;
  
  initial begin
    //p = new();
    pe = new();
    pf = new();
    pe.a = 1;
    p = pe;
    pf.a = 10;
    $display("p.a: %0d", p.a);
    $display("pe.a: %0d", pe.a);
    $display("pf.a: %0d", pf.a);
  end
  
endmodule

In reply to kuki2002:

It might help if you removed the default assignment to type T, which requires you to always provide an override.

class param#(type T);
  T a;
endclass

Then you need to change every occurrence of param without any override to apply what would have been the default.

class param_e#(type T) extends param#(int);
endclass
 
class param_f extends param#(real);
endclass
 
module top;
  param#(int) p;
  param_e#(bit) pe;
  param_f pf;
 
  initial begin
    //p = new();
    pe = new();
    pf = new();
    pe.a = 1;
    p = pe;
    pf.a = 10;
    $display("p.a: %0d", p.a);
    $display("pe.a: %0d", pe.a);
    $display("pf.a: %0d", pf.a);
  end
 
endmodule

Now it is clear that pe’s base class is is the same as p—param#(int).