C# Polymorphism is a key concept in object-oriented programming (OOP) that allows methods, properties, or operators to take multiple forms. The term "polymorphism" means "many forms"; it enables a single interface to be used for different data types by improving code flexibility and reusability. Polymorphism is achieved through method overloading and method overriding, and it allows objects to be treated as instances of their base class. This enhances maintainability and scalability in C# applications.
Example:
C#
// C# Program to demonstrate the concept of Polymorphism
using System;
class Geeks
{
// method without any parameter
public void greet()
{
Console.WriteLine("Hello");
}
// method takes a single string parameter
public void greet(string name)
{
Console.WriteLine("Hello " + name);
}
static void Main(string[] args)
{
Geeks p1 = new Geeks();
// calls method without any argument
p1.greet();
// calls method with an argument
p1.greet("Geeks");
}
}
Explanation: In this example, we have defined a class named "Geeks" containing two methods named greet(). One version of greet() does not require any parameters and prints "Hello". The other version of greet() accepts a parameter and outputs "Hello Geeks". As a result, depending on how greet() is called, it exhibits different behaviours. This capability of greet() to behave differently based on its context demonstrates polymorphism.
Types of Polymorphism
Now that we understand the basics of polymorphism, let's explore its types in C#.
There are two types of polymorphism:
- Compile-time Polymorphism
- Runtime Polymorphism
Compile-time Polymorphism (Method Overloading)
Compile-time polymorphism, also called static polymorphism, is implemented using method overloading. It allows a class to have multiple methods with the same name but different signatures (parameter lists).
It can be differentiated, based perform:
- Changing the number of Parameters
- Changing data types of the parameters.
- Changing the Order of the parameters.
Note: The return value alone is not sufficient for the compiler to figure out which function it has to call. Method overloading is possible only when both methods have different parameter types, resulting in distinct signatures.
1. Changing the number of Parameters
Method overloading can be achieved by varying the number of parameters in a method.
Example:
C#
using System;
class Geeks
{
// Method takes two parameters
// Performs Multiplication
public static int Mathfunct(int a, int b)
{
return a * b;
}
// Method takes three parameters and
// Performs Addition
public static int Mathfunct(int a, int b, int c)
{
return a + b + c;
}
// Method takes four parameters and
// Performs Subtraction
public static int Mathfunct(int a, int b, int c, int d)
{
return a - b - c - d;
}
static void Main(string[] args)
{
int mult = Mathfunct(2, 3);
int add = Mathfunct(2, 3, 4);
int sub = Mathfunct(2, 3, 4, 5);
Console.WriteLine("Multiplication: " + mult);
Console.WriteLine("Addition: " + add);
Console.WriteLine("Subtraction: " + sub);
}
}
OutputMultiplication: 6
Addition: 9
Subtraction: -10
Explanation: In this example, we have three different methods with the same name Mathfunct() but they perform differently and differentiate from each other by several parameters passed in it and each method performs different operations.
2. Changing the Data types of the Parameters
Method overloading can be achieved by changing the data type of a method’s parameters.
Example:
C#
// Overloading by changing the Data types
// of the parameters
using System;
class Geeks
{
// adding three integer values.
public static int Add(int a, int b, int c)
{
int sum = a + b + c;
return sum;
}
// adding three double values.
public static double Add(double a,
double b, double c)
{
double sum = a + b + c;
return sum;
}
public static void Main(String[] args)
{
Console.WriteLine("Add() with integer parameter");
int sum2 = Add(1,2,3);
Console.WriteLine("sum: " + sum2);
Console.WriteLine("Add() with double parameter");
double sum3 = Add(1.0, 2.0, 3.0);
Console.WriteLine("sum: " + sum3);
}
}
OutputAdd() with integer parameter
sum: 6
Add() with double parameter
sum: 6
3. Changing the Order of the Parameters
If the method has the same name but a parameters order of parameters so in this way we can also achieve the method overloading.
Example:
C#
// Illustration of overloading by changing the
// Order of the parameters
using System;
class Geeks
{
public void Identity(String name, int id)
{
Console.WriteLine("Name1 : " + name + ", "
+ "Id1 : " + id);
}
public void Identity(int id, String name)
{
Console.WriteLine("Name2 : " + name + ", "
+ "Id2 : " + id);
}
public static void Main(String[] args)
{
Geeks obj = new Geeks();
// by changing the order
obj.Identity("Geek", 1);
obj.Identity(2, "Geek2");
}
}
OutputName1 : Geek, Id1 : 1
Name2 : Geek2, Id2 : 2
Compile-time Polymorphism (Operator Overloading)
Operator overloading gives the ability to use the same operator to do various operations. It provides additional capabilities to C# operators when they are applied to user-defined data types. It enables user-defined implementations of various operations where one or both of the operands are of a user-defined class.
Example:
C#
// C# program to illustrate the
// unary operator overloading
using System;
namespace Calculator
{
class Calculator
{
public int number1 , number2;
public Calculator(int num1 , int num2)
{
number1 = num1;
number2 = num2;
}
// Function to perform operation
// By changing sign of integers
public static Calculator operator -(Calculator c1)
{
c1.number1 = -c1.number1;
c1.number2 = -c1.number2;
return c1;
}
// Function to print the numbers
public void Print()
{
Console.WriteLine ("Number1 = " + number1);
Console.WriteLine ("Number2 = " + number2);
}
}
class EntryPoint
{
// Driver Code
static void Main(String []args)
{
// using overloaded - operator
// with the class object
Calculator calc = new Calculator(15, -25);
calc = -calc;
calc.Print();
}
}
}
OutputNumber1 = -15
Number2 = 25
Explanation:
- The Calculator the class has a constructor to initialize two integers, number1 and number2.
- The unary operator is overloaded to change the sign of both numbers in the Calculator object.
- In the Main method, the overloaded - operator is used to negate the values of the Calculator object, and the result is printed.
Runtime Polymorphism (Method Overriding)
Runtime polymorphism, or dynamic polymorphism, is achieved by method overriding. Method overriding occurs when a subclass provides a specific implementation for a method that is already defined in the superclass or base class. The method in the subclass must have the same signature as the method in the base class. By overriding a method, the subclass can modify the behaviour of the inherited method. It allows a derived class to provide a specific implementation of a method that is already defined in its base class.
Key Points:
- Virtual Method: The base class method must be declared as virtual to allow overriding.
- Override Keyword: The derived class method must use the override keyword to provide a new implementation.
Example:
C#
using System;
namespace Geeks
{
// Base class
class Animal
{
// Virtual method to allow overriding
public virtual void MakeSound()
{
Console.WriteLine("Animal makes a sound");
}
}
// Derived class
class Dog : Animal
{
// Overriding the base class method
public override void MakeSound()
{
Console.WriteLine("Dog barks");
}
}
// Derived class
class Cat : Animal
{
// Overriding the base class method
public override void MakeSound()
{
Console.WriteLine("Cat meows");
}
}
class Program
{
static void Main(string[] args)
{
Animal myAnimal = new Animal();
Animal myDog = new Dog();
Animal myCat = new Cat();
myAnimal.MakeSound();
myDog.MakeSound();
myCat.MakeSound();
}
}
}
OutputAnimal makes a sound
Dog barks
Cat meows
Explanation: In this example, the 'Animal' class has a 'MakeSound' method. Both the 'Dog' and 'Cat' classes also have their version of MakeSound. The keyword 'override' Make sure that these versions replace the one in Animal.
Different Keywords used in Method Overriding
Let's understand In depth how these keywords are used in method overriding in C#. These keywords are as follows:
- virtual keyword
- override keyword
- base keyword
1. virtual Keyword
The virtual
keyword is used in the base class to define a method that can be overridden in a derived class.
Example 1: This example demonstrates method overriding using virtual keyword.
C#
using System;
class Animal
{
// Base class method marked as virtual
public virtual void Move()
{
Console.WriteLine("Animal is moving.");
}
}
class Dog : Animal
{
// Overriding the base class
// method using 'override'
public override void Move()
{
Console.WriteLine("Dog is running.");
}
}
// Main class
class Geeks
{
static void Main()
{
// Creating an object of the Dog class
Dog dog = new Dog();
dog.Move();
}
}
Explanation: The Move()
method in the Animal
class is declared as virtual
, allowing it to be overridden in the Dog
class using the override
keyword.
Example 2: This example demonstrates method overriding without using virtual and override modifiers.
C#
using System;
// base class name 'baseClass'
class baseClass
{
public void show() { Console.WriteLine("Base class"); }
}
// derived class name 'derived'
// 'baseClass' inherit here
class derived : baseClass {
// overriding
new public void show() {
Console.WriteLine("Derived class");
}
}
// Main class
class Geeks
{
// Main Method
public static void Main()
{
// 'obj' is the object of
// class 'baseClass'
baseClass obj = new baseClass();
// invokes the method 'show()'
// of class 'baseClass'
obj.show();
obj = new derived();
// it will invokes the method
// 'show()' of class 'baseClass'
obj.show();
}
}
OutputBase class
Base class
2. override keyword
This keyword is used in the derived class to provide a specific implementation of a method defined in the base class.
Example: This example demonstrates method overriding using the override keyword.
C#
using System;
class Animal
{
// Base class method marked as virtual
public virtual void Move()
{
Console.WriteLine("Animal is moving.");
}
}
class Dog : Animal
{
// Overriding the base class
// method using 'override'
public override void Move()
{
Console.WriteLine("Dog is running.");
}
}
// Main class
class Geeks
{
static void Main()
{
// Creating an object of the Dog class
Dog dog = new Dog();
dog.Move();
}
}
Explanation: The Move() method in the Dog class uses the override keyword to change the behaviour of the Move() method defined in the Animal class.
3. base Keyword
This method allows accessing methods, properties, or constructors of the base class from within a derived class.
Use of Base Keyword:
- Call methods or functions of base class from derived class.
- Call the constructor internally of the base class at the time of inheritance.
Example 1: This example demonstrates method overriding using the Base keyword.
C#
using System;
class Animal
{
// Base class method marked as virtual
public virtual void Move()
{
Console.WriteLine("Animal is moving.");
}
}
class Dog : Animal
{
// Derived class method that calls
// the base class method using 'base'
public override void Move()
{
// Calls the Move() method
// from the Animal class
base.Move();
Console.WriteLine("Dog is running.");
}
}
// Main class
class Geeks
{
static void Main()
{
Dog dog = new Dog();
dog.Move();
}
}
OutputAnimal is moving.
Dog is running.
Explanation: The Animal class has a Move() method, which is marked as virtual to allow overriding. The Dog class overrides the Move() method and invokes the base class method using base.Move()
, displaying both base and derived class messages. When dog.Move()
is called, it prints "Animal is moving" followed by "Dog is running".
Example 2: This example demonstrates how the base Keyword specifies the calling of the base-class constructor from the derived class when derived class instances are created.
C#
using System;
public class Geeks
{
public Geeks(string Subject)
{
Console.WriteLine(Subject + " Geek started learning ");
}
}
public class CsStudent : Geeks
{
public CsStudent(string Subject) : base(Subject) { }
}
public class MainClass
{
public static void Main()
{
// Calls Geeks constructor
new CsStudent("C#");
}
}
OutputC# Geek started learning
Important Points:
- Method overriding is possible only in derived classes. A method is overridden in the derived class when it is inherited from the base class.
- A non-virtual or static method cannot be overridden.
- Both the overridden method and the virtual method must have the same access level modifie
Use Case and Behavior of Polymorphism
- Allows methods to be written in a more general form, making code easier to extend and maintain.
- Enhances the flexibility of the code and makes it easier to maintain.
- Enables the use of a uniform interface, which simplifies the design of systems that can handle different data types and objects consistently.