Polymorphism in C#

Polymorphism is one of the three basic components of Object Oriented Programming (OOP). Polymorphism literally means having multiple shapes. In terms of programming, it is referred to as “one interface, multiple functions.”  In C#, polymorphism is implemented via method overloading, method overriding and inheritance. We will look at all of these concepts in detail in this article. Polymorphism can be broadly classified into two categories: static polymorphism and dynamic polymorphism. Static polymorphism is implemented via method overloading, and dynamic polymorphism is implemented via inheritance and method overriding.

Static Polymorphism

To understand static polymorphism we first need to understand static binding or what is called early binding. It basically refers to binding an object with its corresponding functions at runtime. Therefore in static polymorphism, the function that will be called in response to a function call is decided at runtime in static binding. Function overloading is a perfect example of static polymorphism.

Method Overloading

In method overloading, multiple methods with the same name are defined. These methods differ in terms of the type and number of parameters they accept. Note that methods with the same parameters and different return types are not considered different, they must have a different type or number of parameters in order to be overloaded. When you call a method, the method will be called whose parameters match to those in the method call. Take a look at the following example to understand method overloading.

static void Main(string[] args)
{
    OverloadFunc(); // Call with no parameters
    OverloadFunc(10, 20); // Call with two int parameters
    OverloadFunc("John", 2);
}

static void OverloadFunc()
{
    Console.WriteLine("This is a method with no parameters.");
}

static void OverloadFunc(int a, int b)
{
    Console.WriteLine("This is a method with two integer parameters.");
}

static void OverloadFunc(string a, int b)
{
    Console.WriteLine("This is a method with one string and one integer parameters.");
}

Have a look at the above code. In addition to the Main method, it contains three more methods. All of these three methods have a same name “OverloadFunc”. However, the first method takes no parameters. Similarly, the second method takes two integer type parameters and the third method takes one string and one integer type parameter. This means that we have overloaded the ‘OverloadFunc’ by changing the type and number of parameters they accept.

Now, if you look in the main function, “OverloadFunc” is called three times. First, it is called without any parameters; this will execute the corresponding “OverloadFunc” which takes no parameter. In the second call to “OverloadFunc” two integer type variables have been passed as parameters. This will invoke the corresponding method with two integer parameters. Finally, one integer and one string parameter is passed to “OverloadFunc” method. This will invoke the third and final overloaded method.

Now if you run the above code, the output will look like this:

This is a method with no parameters.
This is a method with two integer parameters.
This is a method with one string and one integer parameters.

Dynamic Polymorphism

In dynamic polymorphism, the concept of late binding or dynamic binding comes into play. In dynamic binding, functions are linked to the object at runtime depending upon the nature of the object.

Inheritance Example

To understand polymorphism you first need to understand inheritance. Polymorphism refers to the ability of one class to inherit properties of the parent class. When you inherit a class from a parent class, all the variables and methods of the parent class are accessible to the child or derived class. Take a look at the following example to understand inheritance.

class Vehicle
{
    public void DisplayVehicleMessage()
    {
        Console.WriteLine("This is a method in parent class.");
    }
}

class Car : Vehicle
{
    public void DisplayCarMessage()
    {
    Console.WriteLine("This is a method in child car class.");
    }
}

class Truck : Vehicle
{
    public void DisplayTruckMessage()
    {
        Console.WriteLine("This is a method in child truck class.");
    }
}

In the above code, a class named Vehicle has been defined. It contains one method i.e. “DisplayVehicleMessage”. Next, a class named Car has been defined. This class inherits the Vehicle class. This means that “DisplayVehicleMessage” function is readily accessible to the Car class. Similarly, another class named Truck has been initialized and it also inherits the Vehicle class.

To see how Car and Truck classes call the parent class method “DisplayVehicleMessage”, take a look at the following code.

Vehicle vehicle = new Vehicle();
vehicle.DisplayVehicleMessage();

Car car = new Car();
car.DisplayVehicleMessage();
car.DisplayCarMessage();

Truck truck = new Truck();
truck.DisplayVehicleMessage();
truck.DisplayTruckMessage();

The output of the above code will look like this.

This is a method in parent class.
This is a method in parent class.
This is a method in child car class.
This is a method in parent class.
This is a method in child truck class.

Now that you have a basic understanding of inheritance, let’s move towards implementing polymorphism via inheritance.

Implementing Polymorphism via Inheritance

In the last example, parent class had its own method “DisplayVehicleMessage” while child Car and Truck classes had access to “DisplayVehicleMessage” via inheritance. The child Car and Truck classes did not have their own versions of “DisplayVehicleMessage”. What if the child classes also had their own version of “DisplayVehicleMessage”? Which method would then be called via objects of the Car and Truck classes? Would it be the parent version of the “DisplayVehicleMessage” method or the child versions of the method? This is where polymorphism comes into play. Have a look at the following example.

class Vehicle
{
    public virtual void DisplayVehicleMessage()
    {
        Console.WriteLine("This is a method in parent class.");
    }
}

class Car : Vehicle
{
    public override void DisplayVehicleMessage()
    {
        Console.WriteLine("This is a method in child car class.");
    }
}

class Truck : Vehicle
{
    public override void DisplayVehicleMessage()
    {
        Console.WriteLine("This is a method in child truck class.");
    }
}

Now take a look at the above code, here we marked the parent “DisplayVehicleMessage” as virtual. This means that all the child classes can override this method and can have their own implementation of the method. In the child Car and Truck classes, the method is overridden via “override” keyword.

Now all the three classes have the same “DisplayVehicleMessage” with different implementations. We all know that a child class object can be stored in parent class reference variable. Therefore, we can store Car and Truck objects in Vehicle class reference. Take a look at the following to see how “DisplayVehicleMessage” is called via the objects of Vehicle, Car, and Truck classes.

Vehicle vehicle = new Vehicle();
vehicle.DisplayVehicleMessage();

Vehicle car = new Car();
car.DisplayVehicleMessage();

Vehicle truck = new Truck();
truck.DisplayVehicleMessage();

Take a look at the above code. We have created Vehicle, Car and Truck objects and stored them in the reference variable of the parent Vehicle class. Next, we called the “DisplayVehicleMessage” on each variable. Now the question here is that which version of “DisplayVehicleMessage” will be called via reference variables of type Vehicle. The answer is that during program execution dynamic binding will occur and the runtime will look for the type of object stored in the vehicle reference variable and will execute the corresponding method.

For instance, the first Vehicle type reference variable “vehicle” stores a referent to the Vehicle type object. Therefore, when “DisplayVehicleMessage” is called via the “vehicle” variable, the method that belongs to the Vehicle class will be called. Similarly, the second vehicle type reference “car” stores referent to the child class object Car. Therefore, when “DisplayVehicleMessage” is called via the “car” variable, the method that belongs to Car class will be called. Likewise calling “DisplayVehicleMessage” via the “truck” variable will execute the method that belongs to the Truck class.

In short, we are having the same Vehicle type reference variables executing different methods, depending upon the object that the variables hold, which is polymorphism. One interface, multiple methods.

The output of the above code will look like this:

This is a method in parent class.
This is a method in child car class.
This is a method in child truck class.

In this article, we discussed polymorphism in C#. We discussed what it is and how it is beneficial in programming. I hope you now understand how to use polymorphism when designing your classes. As always, if you have any questions or comments, let me know in the comments section below. If you found this article helpful be sure to check out my C# Roadmap.