SystemVerilog Datatype: Class (Part 3)
Previous: Data encapsulation |
Next: Class scope resolution
Be Abstract, Be Virtual - Abstract Classes, Virtual Methods
Recall from our earlier discussion that a subclass extends the
definition of a base class.
Now, suppose you only need various subclasses that extend one single base
class in your application, but you do not need (and do not want anyone
else to access) the base class itself. In order to encapsulate the use of
the base class, you declare it as virtual. If we want Triangle
to be such a base class, then the following example shows how to do it.
virtual class Triangle;
...
endclass
In this example, the base class Triangle can be extended by other
subclasses, but Triangle itself can not be instantiated. A virtual
base class is also called an abstract class.
The keyword virtual can also be used to qualify a method (in
a virtual or regular class). In this case, the method contains only an
empty prototype definition, the actual definition is contained within
each subclass, if it uses that method.
The following example ilustrates this. Here, Triangle is a virtual
class that has a virtual method (in this case, a task) fillIt().
The virtual task definition is empty, and the real definition is provided
inside the subclass Trapezoid.
virtual class Triangle;
...
virtual task fillIt (struct rgb color);
endtask // empty declaration
endclass
class Trapezoid extends Triangle;
point p4;
task fillIt (struct rgb color);
... // detail definition here
endtask
endclass
Polymorphism
Polymorphism, according to Merriam-Webster online dictionary, is 'the quality
or state of being able to assume different forms.' The phenomenon of polymorphism
perhaps can be best explained by the following example. Here, triangle_array
is an array of base class Triangle. Trapezoid is a sub-class of
Triangle and just like Triangle that has a method fillIt().
Since there is a common method name, as we know, an object instance will choose
the method corresposding to its class. The variables t and tzpd
are object instances of Triangle and Trapezoid respectively.
Now, assume index is a variable that is available only during run time
(perhaps it is an input from an external file).
Triangle [NN:0] triangle_array;
class Trapezoid extends Triangle;
...
task fillIt;
...
endtask
endclass
Triangle t = new;
Trapezoid tpzd = new;
...
if (index)
triangle_array[0] = t;
else
triangle_array[0] = tpzd;
...
triangle_array[0].fillIt();
// The all important task call
...
Now carefully note the last few lines of the above code snippet. We are
assigning to triangle_array[0] a variable based on a run time value.
Moreover, the right hand side of this assignment can be the base class or
a sub class. There is no way for a compiler to know the content of
triangle_array[0] until the run time. However, due to polymorphism,
we are allowed to do the assignment.
Also notice that we are allowed to call triangle_array[0].fillIt()
which will point to the appropriate method (either the fillIT() method
of Triangle or the fillIT() method of Trapezoid). All
these are decided at the run time.
Previous: Data encapsulation |
Next: Class scope resolution
|