2016年2月3日星期三

What is the usage for virtual function in C#?



A virtual function, is basically saying look, here's the functionality that may or may not be good enough for the child class.  So if it is good enough, use this method, if not, then override me, and provide your own functionality.  We can see the difference between a virtual function and an abstract function: An abstract function can have no functionality. You're basically saying, any child class MUST give their own version of this method, however it's too general to even try to implement in the parent class.

But  what if i don't use virtual keyword in base class?  and is it compulsory to override virtual method in derived classes?  

When there is no virtual keyword in base class, You will generate compiler error CS0506  if you try to override the method with 'Override' keyword in descendent classes. But you can use 'new' keyword to replace the method in base class.

new public int Method() 
{
     ... 
}
And it is not compulsory to override virtual method in derived classes. The descendent class will use method it is inheriting from.


Then, why do we need virtual function? The key to understand the practical usage of virtual functions is to keep in mind that an object of a certain class can be assigned another object of a class derived from the first object's class. E.g.:

class Animal{
   public void eat(){...}
}
class FlyingAnimal:Animal{
   public void eat(){...}
}
Animal a = new FlyingAnimal();

The Animal class has a function eat() that generally describes how an animal should eat (e.g. put the object in mouth and swallow).

However, the FlyingAnimal class should define a new eat() method, because flying animals have a particular way of eating.

So the question that comes to mind here is: after I declared the variable a of type Animal and assigned it a new object of type FlyingAnimal, what will a.eat() do? Which of the two methods is called?

The answer here is: because a is of type Animal, it will call Animal's method. The compiler is dumb and doesn't know that you are going to assign an object of another class to the a variable.
Here is where the virtual keyword comes in action: if you declare the method as virtual void eat() {...}, you are basically telling the compiler "be careful that I am doing some clever stuff here that you cannot handle because you're not as smart". So the compiler will not attempt to link the call a.eat() to either of the two methods, but instead it tells the system to do it at runtime!

So only when the code executes, the system will look at a's content type not at its declared type and executes FlyingAnimal's method.

You may wonder: why the hell would I want to do that? Why not say right from the start ? like:

FlyingAnimal a = new FlyingAnimal() 

The reason for that is that, for example, you may have many derived classes from
 AnimalFlyingAnimalSwimmingAnimalBigAnimalWhiteDog etc. And at one point you want to define a world containing many Animals, so you say:

Animal[] happy_friends = new Animal[100];

We have a world with 100 happy animals. You initialize them at some point:

...
happy_friends[2] = new AngryFish();
happy_friends[10]= new LoudSnake();

And at the end of the day, you want everybody to eat before they go to sleep. So you want to say:

for(int i=0; i<100; i++){
   happy_friend[i].eat();
}

So as you can see, each animal has its own method of eating. Only by using virtual functions can you achieve this functionality. Otherwise, everyone would be forced to "eat" in the exact same way: as described in the most general eat function inside the Animal class.

By the way, this behaviour is actually default in common high-level languages like Java.