Polymorphism
Polymorphism is one of the four fundamental principles of object-oriented programming (OOP) in C#. It allows objects of different types to be treated as instances of a common base type. This enables a single interface to be utilized with various underlying data types. In C#, there are two types of polymorphism:
- Compile-time polymorphism (also known as static polymorphism)
- Run-time polymorphism (also known as dynamic polymorphism)
Compile-Time Polymorphism
Compile-time polymorphism is achieved through method overloading and operator overloading. This form of polymorphism is resolved during the compilation of the code.
Example of Compile-Time Polymorphism
using System;
class Calculator
{
 // Method to add two integers
 public int Add(int a, int b)
 {
   return a + b;
 }
  // Overloaded method to add three integers
 public int Add(int a, int b, int c)
 {
   return a + b + c;
 }
  // Overloaded method to add two doubles
 public double Add(double a, double b)
 {
   return a + b;
 }
}
class Program
{
 static void Main()
 {
   Calculator calc = new Calculator();
   Console.WriteLine(calc.Add(2, 3));      // Calls Add(int, int)
   Console.WriteLine(calc.Add(1, 2, 3));     // Calls Add(int, int, int)
   Console.WriteLine(calc.Add(2.5, 3.5));    // Calls Add(double, double)
 }
}
Run-Time Polymorphism
Run-time polymorphism is achieved through method overriding. This type of polymorphism is resolved at run time. Method overriding allows a derived class to provide a specific implementation for a method that is already defined in its base class
Example of Run-Time Polymorphism
using System;
// Base class
class Animal
{
 // Virtual method to be overridden in derived classes
 public virtual void Speak()
 {
   Console.WriteLine("The animal makes a sound.");
 }
 // Method to display the animal's type
 public void DisplayType()
 {
   Console.WriteLine("This is an animal.");
 }
}
// Derived class
class Dog : Animal
{
 // Overriding the Speak method
 public override void Speak()
 {
   Console.WriteLine("The dog barks.");
 }
  // Method specific to Dog
 public void Fetch()
 {
   Console.WriteLine("The dog fetches the ball.");
 }
}
// Derived class
class Cat : Animal
{
 // Overriding the Speak method
 public override void Speak()
 {
   Console.WriteLine("The cat meows.");
 }
  // Method specific to Cat
 public void Scratch()
 {
   Console.WriteLine("The cat scratches the furniture.");
 }
}
class Program
{
 static void Main()
 {
   // Create instances of Dog and Cat
   Animal myDog = new Dog();
   Animal myCat = new Cat();
    // Demonstrate run-time polymorphism
   myDog.Speak(); // Outputs: The dog barks.
   myCat.Speak(); // Outputs: The cat meows.
    // Demonstrate base class method
   myDog.DisplayType(); // Outputs: This is an animal.
   myCat.DisplayType(); // Outputs: This is an animal.
   // Directly accessing methods specific to Dog and Cat
   Dog specificDog = new Dog();
   Cat specificCat = new Cat();
   specificDog.Fetch(); // Outputs: The dog fetches the ball.
   specificCat.Scratch(); // Outputs: The cat scratches the furniture.
 }
}
Benefits of Polymorphism
- Code Reusability: Polymorphism enables code reuse by allowing a base class to manage common functionality while derived classes provide specific implementations.
- Maintainability: Code becomes easier to maintain and extend because changes in the base class automatically affect derived classes.
- Flexibility: Polymorphism enhances flexibility by permitting objects to be treated as instances of their base type, which facilitates easier integration and interaction among different objects.
- Dynamic Behavior: Polymorphism supports dynamic method binding at runtime, ensuring that the appropriate method implementation is called based on the actual object type.
