The use of inheritance and polymorphism has become an integral part of our life as a programmer. Inheritance provides a lot of benefits including code reusability, separation of concerns, cleaner code, extensibility etc.
Polymorphism is one of the three main concepts of object-oriented programming, the other two being Encapsulation and Inheritance. Polymorphism is frequently used with inheritance. By polymorphism here, I mean run-time polymorphism or method overriding. Compile time polymorphism or method overloading does not require inheritance.
We are going to discuss method overriding here with some examples.
Method overriding is a feature that allows an object of a base class to call the methods (with the same name, parameters, and return type) of a base class as well as derived class based on the instance of the class it holds.
Note: Reference type assignments in C# work with Covariant mode, so you cannot assign the instance of a base class to a derived class object.
For example - I have a base class Fruit with the function Details(). There is another class Mango which inherits Fruit but also has a function named Details().
public class Fruit
{
public void Details()
{
-----------
}
-----------
}
public class Mango : Fruit
{
public void Details()
{
-----------
}
-----------
}
Through overriding, an object of Fruit can call Details() of Fruit, if it stores the instance of Fruit. object of Fruit can call the method- Details of class Mango, if it stores the instance of class Mango.
Fruit a = new Fruit();
a.Details(); // Should call the method- Details of base class Fruit
a = new Mango();
a.Details(); // Should callthe method- Details of derived class Mango
Ok, so we learned what is overriding.
But practically, to achieve this, we may need to use a couple of keywords and we are going to check them out.
These keywords are – virtual, override, and new.
Virtual and Override
We use these two keywords to achieve the overriding functionality mentioned above. We can have a better understanding if we do it with some samples.
Open Visual Studio, go to File -> New -> Project -> Console App, and name it as OverridingSample.
I have added a class named Inheritance to the project. Open the Overriding.cs and remove the default class in it.
Add two classes named Base and Derived, as below.
public class Base
{
public Base()
{
}
}
public class Derived : Base
{
public Derived()
{
}
}
The derived class inherits from the Base class. Then, add a method Function1() to the Base class as below.
public void Function1()
{
}
Add the same method to the Derived class as well.
You can notice one thing that the compiler raises warning that it hides the Base.Function1() and if that is intended, you can add a new keyword.
You can build the project. You will see that despite having this compiler warning, the project gets compiled successfully. To test how this works, I created a class called TestOverriding and added the code as mentioned below.
// Without using virtul, override and new
public void Test1()
{
Base b = new Base();
b.Function1();
Derived d = new Derived();
d.Function1();
Base bd = new Derived();
bd.Function1(); // Doesn't work as per overriding principle
}
I have declared three objects,
- The first one is of type Base and holds an instance of Base class.
- The second one is of type Derived and holds an instance of a Derived class.
- The third one is of type Base and holds an instance of the Derived class.
Now, create an object of the TestOverriding class in the Program.cs and call the method Function1().
TestOverriding overriding = new TestOverriding();
overriding.Test1();
It will create the following output.
While the first two function calls work as expected, the third function call doesn’t work as expected as per the overriding principle.
As per overriding principle, though bd was of type Base, when it is initialized with object Derived, it should have invoked the method of the Derived class.
Here comes the role of override keyword.
If we add the virtual keyword before the base class method and override keyword before the derived class method, we can solve the above problem. I am going to create a new method called Function2 to demonstrate how override keyword works.
Add the below method to the base class.
virtual public void Function2()
{
Console.WriteLine("Base - Function 2");
}
Also, add the below code to the derived class.
override public void Function2()
{
Console.WriteLine("Derived - Function 2");
}
Note that you can add virtual and override keywords either before or after the public keyword.
Test2() looks like below.
// Uses virtual in base class and used override in derived class.
public void Test2()
{
Base b = new Base();
b.Function2();
Derived d = new Derived();
d.Function2();
// Watch this out to check if overriding works
Base bd = new Derived();
bd.Function2();// This works as expected
}
Call the method Test2(),
overriding.Test2();
and here is the output.
Now, we can see that all the scenarios work as expected especially, the third which works as per the overriding principle.
Now, we can check what happens if I remove virtual or override from the two methods in the base and derived classes.
Base class method declared as virtual and derived class declared without overriding
First, I am going to remove the override keyword from the derived class while keeping the virtual in the base class.
Base class method
virtual public void Function2()
{
Console.WriteLine("Base - Function 2");
}
Derived class method
public void Function2()
{
Console.WriteLine("Derived - Function 2");
}
I am getting a compile time warning here but the contents here contain two suggestions instead of one, in case of Test1().
The warning first suggests using override keyword, mainly because of the fact that we have defined the base class as virtual. The compiler is smart enough to assume that you may have missed adding override keyword in the derived class.
But the result, if we run the above code, is same as that of the Test1().
Base class method note declared as virtual and derived class declared as overriding
Now, add the override back to the derived class method and remove virtual from the base class.
The functions should look like this.
Base class method
public void Function2()
{
Console.WriteLine("Base - Function 2");
}
Derived class method
override public void Function2()
{
Console.WriteLine("Derived - Function 2");
}
Here, you have the compiler error shown which is obvious.
Take away
- For overriding to work as expected, you should declare the base class as virtual and use override keyword in the derived class to override it.
- Virtual and override work together to get the desired result and you cannot override a class which is not marked as virtual.
- Declaring the base class as virtual and not decorating the derived class with override keyword means you are not overriding the method.
A little advanced scenario
Since we have learned the basics, now we can try a more realistic scenario.
I am going to add a method named Show in base class. Unlike other methods we have created so far, I am not going to write the overridden method in the derived class.
// All objects call the same method in base class which calls other overridden methods
public void Test3()
{
Base b = new Base();
b.Show();
Derived d = new Derived();
d.Show();
// Watch this out to check if overriding works
Base bd = new Derived();
bd.Show(); // This works as expected
}
I am going to call the same Show() using 3 different objects in Test3(),
overriding.Test3();
Here you have the output:
The first scenario, which base type object and base type instance behaves very normally. We are calling the Show method of base class and which in turn calls the base class methods, Function1 and Function2.
But in the case of second method call, which has type of derived and instance of derived, it is worth checking the Function1().
Here also we calling the Show() of base class which in turn calls the Function1() and Function2(). Since we have not declared the Function1() as virtual and used override in derived class, the base class method, Show() cannot call the derived calls Function1(). On the other hand, since Function2() is defined as virtual and overridden in derived class, Show() is able to call the Function2() of derived class.
Third example, works exactly like second, since the object holds the instance of derived class itself.
Override keyword is not only used with virtual, it is also used with abstract.
If a base class declares a method as abstract, the method need to be defined in the derived class using override keyword.
New Keyword
Adding new keyword to a method tells that you are aware that the method hides the base class method.
Remember, in Test1() we have seen that when we use the same method name in derived class and does not use override keyword, we will get a compiler warning: “Derived class method … hides the base class method …., if the hiding was intended, use new keyword.”.
New keyword suppresses the warning in shown in Test1() but doesn’t change anything in the output.
Let us create a new method and write a test method for this.
Add the below method to our base class,
public void Function3()
{
Console.WriteLine("Base - Function 3");
}
Then add the below method to our derived class,
new public void Function3()
{
Console.WriteLine("Derived - Function 3");
}
You can see that new keyword is added before the Fucntion3().
Just like virtual and override, you can add the new keyword before or after the public keyword.
New keyword suppresses the warning.
Let’s create a test method now,
// Uses new in derived class and not used virtual in base class.
public void Test4()
{
Base b = new Base();
b.Function3();
Derived d = new Derived();
d.Function3();
Base bd = new Derived();
bd.Function3();
}
Call the test method,
overriding.Test4();
and here is the output
We can see that the output is like the output of Test1() where we neither used virtual nor new.
Only difference is new suppresses the warning and we are making sure we know that the method is not overridden.
We cannot use override and new to qualify the same method because they are mutually exclusive in nature.
Though object bd contains instance of Derived class, since we have mentioned the Function3() as new, it cannot access the Function3() of Derived class. This is because, it takes overriding to call the method of derived class when the object holds the instance of derived class. By using new, we have clearly mentioned that we are not using overriding here instead it is a new method with the same name.
Hope you understood the use of virtual, override and new keywords and what is overriding in c#.
You can download and use the attached source code to play with it further.