Introduction to Polymorphism in C#
Polymorphism is a concept achieved in object-oriented programming languages like C#, where an operator or a functional method can take more than one form throughout the execution process. It is widely used for the implementation of inheritance in the program, and this is categorized into two methods, namely Operator overloading and function overloading. In simple words, Polymorphism can be explained as a technique for altering the base class using the derived class, where both the classes possess different properties.
The following diagram illustrates the working of polymorphism:
This figure explains that clay is the parent object from which pot, bowl, and toy objects are made. All of these objects are different from each other, but they have the properties of clay. These three objects have different shapes and are used in different ways even when they are made from the same material, clay.
Forms of Polymorphism
Below are the 2 forms of Polymorphism:
1. Operator Overloading
An Operator can give different outputs based on the type of operands that it is operating on. This is called Operator Overloading. E.g., the operator ‘+’ can perform addition on two integers, while it can concatenate two strings. Thus the same operator can be used in 2 different ways. The addition operator generally adds two numbers. However, in the case of complex numbers, the addition is a bit different, where the corresponding real parts and imaginary parts are separately added. Here is an example code that shows how ‘+’ operator can be overloaded to add complex numbers.
Code:
using System;
namespace Overload {
class Complex
{
public double x;
public double y;
// no-argument constructor
public Complex() {}
// parameterized constructor
public Complex(double real, double img)
{
x = real;
y = img;
}
// Overloading of Binary "+" operator
public static Complex operator + (Complex c1,
Complex c2)
{
Complex c3 = new Complex();
c3.x = c1.x + c2.x;
c3.y = c1.y + c2.y;
return c3;
}
// function to display result
public void display()
{
Console.WriteLine("{0} + {1}i", x,y);
}
}
class CalNum {
// Driver Code
static void Main(string[] args)
{
Complex num1 = new Complex(2.5,3.5);
Complex num2 = new Complex(1.2,6.5);
Complex num3 = num1 + num2;
Console.Write("c1 = ");
num1.display();
Console.Write("c2 = ");
num2.display();
Console.Write("c3 = ");
num3.display();
}
}
}
Output:
This output illustrates operator overloading to add two complex numbers. The code shows operator overloading as well as function overloading.
2. Function Overloading
A function can give different outputs based on the number of parameters as well as their return types and the function return type. The above-mentioned code also covers function overloading using a constructor. There are 2 constructors in the code; one is the default constructor which is left empty while the other is a parameterized constructor which is used to initialize the complex number with the values mentioned as parameters.
Taking the example illustrated in the figure, the function is molding the clay and the stroke direction is the member provided to mold the clay. Based on different stroke directions, clay gets transformed into the pot, bowl, and toy respectively.
Code:
using System;
using System.Collections.Generic;
public class Clay
{
// A few example members
public int Height { get; set; }
public int strokeDirection { get; set; }
// Virtual method
public virtual void Mould()
{
Console.WriteLine("Beginning to mould the clay");
}
}
class Pot : Clay
{
public override void Mould()
{
// Code to make a pot Console.WriteLine("Making a pot");
base.Mould();
}
}
class Bowl : Clay
{
public override void Mould()
{
// Code to make a bowl
Console.WriteLine("Making a bowl");
base.Mould();
}
}
class Toy : Clay
{
public override void Mould()
{
// Code to make a toy
Console.WriteLine("Making a toy");
base.Mould();
}
}
class Program
{
static void Main(string[] args)
{
// Illustrating Polymorphism #1: a Pot, Bowl and Toy
// can all be used wherever Clay is expected. No cast is
// needed because an implicit conversion exists from a derived
// class to its base class.
var items = new List<Clay>
{
new Pot(),
new Bowl(),
new Toy()
};
// Polymorphism at work #2: the virtual method Mould is
// invoked on each of the derived classes, not the base class.
foreach (var item in items)
{
item.Mould();
}
}
}
Output:
As you may have noted in the code, the clay class is the parent class whose child classes are pot, toy, and bowl classes. The method ‘Mould’ is defined in the parent class as well as the child class with the same function signature. Hence, when an object of the child class is created and it calls the method Mould, the base class method gets overridden by the child class method. Thus, we see the output of the child class method. The above code shows method overriding and not overloading to illustrate polymorphism.
Points to be Kept in Mind for Polymorphism in C#
The points that are to be kept in mind for polymorphism in C#:
- Overloading is different from Overriding. Overloading has different function signatures while overriding has the same function signatures.
- Polymorphism refers to changing the behaviour of a superclass in the subclass.
- Inheritance refers to using the structure and behaviour of a superclass in a subclass.
Following are the few key takeaways:
- Polymorphism is one of the major paradigms of Object-Oriented programming.
- Function overloading modifies the function as per the return types and parameters of the function in the inherited class.
- Operator overloading modifies the operator definition as per given parameters.
- Polymorphism is used to implement inheritance. It decides at run time to call the child class method using method overriding.
Recommended Articles
This is a guide to Polymorphism in C#. Here we discuss the working of polymorphism, two forms of polymorphism with sample code along with few key takeaways. You may also look at the following article to learn more –