In reply to nchakravarthy:
Nikhil,
There are some problems in the terminology of your questions. You do not call modules or interfaces, you instantiate them. We use the word instantiate to mean come into existence. And modules and interfaces can only be statically instantiated , which means they come into existence at the start of a simulation before time 0. To call something means to activate a procedural set of statements encapsulated in a task or function, and you can call a task or function declared inside an interface. Another problem is in understanding the difference between a variable and the handle that refers to an instance.
Class objects can only be dynamically instantiated by calling its constructor function. However, class variables that eventually hold handles to class objects can be statically or dynamically instantiated. See A Short Class on SystemVerilog Classes - Verification Horizons for more info on that.
It is certainly possible for a class method to call a function declared inside an interface instance directly. The problem lies in where we want to define the class and keeping the testbench independent from the DUT hierarchy.
Most class-based testbenches are declared inside a package, and packages do not allow any references to objects outside that package except by import of another package. And even if they were allowed, we would not want a hard-coded hierarchical paths inside our testbench code as this makes the class less reusable.
There are at least two ways to deal with referencing hierarchical paths from a class defined in a package. SystemVerilog allows you to declare a virtual interface variable that holds a handle to a static interface instance. From the top level testbench module, you can dynamically construct a class that has a virtual interface variable inside it and then assign the variable with a handle that has the path to interface instance. This works very similar to a class variable with a handle to a dynamic class instance except the instance the variable refers to is now a static instance.
There are a number of limitations when referring to a static instance through a virtual interface variable. The biggest one is the fact that any parameter overrides when instantiating an interface instance have to be matched with parameter overrides when declaring a virtual interface variable. It is very difficult to propagate those parameter overrides to the testbench. So another technique has been developed that avoids virtual interface variables altogether and instead uses abstract classes. But I think you should fully understand the virtual interface issues before exploring getting rid of them.