C# Polymorphism


  • Polymorphism means one name, many forms.
  • Polymorphism is the ability for classes to provide different implementation to the method that are called by same name.
  • Polymorphism can be of two types:
    • Static Polymorphism
    • Dynamic Polymorphism

Static Polymorphism:


  • In static polymorphism decisions are made at compile time.
  • It is also known as early binding.
  • Static polymorphism can be understand by two terms:
    • Method overloading
    • Operator overloading
Method Overloading

  • Method overloading is a concept where a class can have more than one method with the same name and different parameters.
  • It is a static type polymorphism because in it compiler checks the type and number of parameters passed on to the method and decides which method to call at compile time and it will give an error if there are no methods that match the method signature of the method that is called at compile time.
  • You cannot overload function declarations that differ only by return type.
  • Here is an example of the Method Overloading:
Example

using System;
namespace MethodOverloading
{
class Program
{
public class TestOverloading
{

public void Add(string a1, string a2)//method add with integer parameter
{
Console.WriteLine("Adding Two string :" + a1 + a2);
}

public void Add(int a1, int a2)//method add with integer parameters
{
Console.WriteLine("Adding Two Integer :" +( a1 + a2));
}
public void Add(float a1, float a2)//method add with float parameter
{
Console.WriteLine("Adding Two real numbers :" +( a1 + a2));
}
}

static void Main(string[] args)
{
TestOverloading obj = new TestOverloading();

obj.Add("Ram ", "Sharma");

obj.Add(5, 10);
obj.Add(5.5f, 5.5f);

Console.ReadLine();
}
}
}

The output of the above program will be as follows:


Output

Adding Two string: Ram Sharma
Adding Two Integer:15
Adding Two real numbers:11

Operator Overloading

  • Operator overloading is a technique of static type polymorphism.
  • We can use the operators like '+','-','++','--','*' and many more for the primitive data type directly but we cannot apply this operators directly for the user defined data types like class-objects or instance of structure. So to use the operators for the user defined data types operator overloading is used.
  • Operator overloading is a process in which more than one meaning is given to the operator without changing its syntax. The compiler distinguishes between the different meanings of an operator by examining the types of its operands.
  • Basic Syntax for the operator overloading:
  • polymorphism

Here is the list of some operators that can be overloaded and some that cannot be overloaded as sown in the tables given below:


Operators that can be overloaded

polymorphism
Operator that cannot be overloaded

polymorphism

Here is an Example of overloading of binary operator '+':


Example

using System;
namespace operatoroverloading
{
class overload
{
public int x;
public int y;
public int z;
public overload()
{
x = y = z = 0;
}
public overload(int a, int b, int c)
{
x = a;
y = b;
z = c;
}
public static overload operator +(overload obj1, overload obj2)
{
overload obj3 = new overload();
obj3.x = obj1.x + obj2.x;
obj3.y = obj1.y + obj2.y;
obj3.z = obj1.z + obj2.z;
return obj3;
}
public void display()
{
Console.WriteLine("x={0},y={1},z={2}", x, y, z);
}

static void Main()
{
overload ob1 = new overload(5, 6, 7);
overload ob2 = new overload(2, 3, 4);
overload ob3 = new overload();
Console.WriteLine("Elements of Object1:");
ob1.display();
Console.WriteLine("Elements of Object2:");
ob2.display();
ob3 = ob1 + ob2;
Console.WriteLine("Elements of Object3 after addition Object1 and Object2:");
ob3.display();
Console.ReadLine();

}
}
}

The output of the above program will be as follows:


Output

Elements of Object1:
x=5, y=6, z=7
Elements of Object2:
x=2, y=3, z=4
Elements of Object3 after addition Onject1 and Object2:
x=7, y=9, z=11

Dynamic Polymorphism


  • In dynamic polymorphism decisions are made at run time.
  • It is also known as late binding.
  • Dynamic Polymorphism is applied using Abstract Classes and Virtual Functions.
  • Let us discuss Abstract Classes and Virtual Functions one by one:
Abstract Classes

  • A class that provides no implementation or incomplete implementation of its functionalities and leaves the task to implement its functionalities to its derived class is known as Abstract class.
  • An Abstract class contains Abstract methods that do not have method bodies. The actual implementation of these abstract methods is done in the classes derived from the abstract classes.
  • An Abstract class cannot be instantiated.
  • Abstract class is always public.
  • Declaring an Abstract Class

    Abstract class is declare using abstract keyword its basic syntax is given below:


    public abstract class classname
    {
    //content methods of an abstract class
    }

    Here is a simple example of Abstract class as follows:


    Example

    using System;
    namespace PolymorphismApplication
    {
    abstract class Shape
    {
    public abstract int area();
    }
    class Rectangle: Shape
    {
    private int length;
    private int width;
    public Rectangle( int a=0, int b=0)
    {
    length = a;
    width = b;
    }
    public override int area ()
    {
    Console.WriteLine("Rectangle class area :");
    return (width * length);
    }
    class RectangleTester
    {
    static void Main(string[] args)
    {
    Rectangle r = new Rectangle(10, 7);
    double a = r.area();
    Console.WriteLine("Area: {0}",a);
    Console.ReadKey();
    }
    }
    }

    When the above code is compiled and executed, it produces the following result:


    Output

    Rectangle class area :
    Area: 70

    Virtual Functions

    When you have a function defined in a class that you want to be implemented in an inherited class(es), you use virtual functions. The virtual functions could be implemented differently in different inherited class and the call to these functions will be decided at runtime.


    Here is a simple example of Virtual Function as follows:


    Example

    using System;
    namespace PolymorphismApplication
    {
    class Shape
    {
    protected int width, height;
    public Shape( int a=0, int b=0)
    {
    width = a;
    height = b;
    }
    public virtual int area()
    {
    Console.WriteLine("Parent class area :");
    return 0;
    }
    }
    class Rectangle: Shape
    {
    public Rectangle( int a=0, int b=0): base(a, b)
    {
    }
    public override int area ()
    {
    Console.WriteLine("Rectangle class area :");
    return (width * height);
    }
    }
    class Triangle: Shape
    {
    public Triangle(int a = 0, int b = 0): base(a, b)
    {
    }
    public override int area()
    {
    Console.WriteLine("Triangle class area :");
    return (width * height / 2);
    }
    }
    class Caller
    {
    public void CallArea(Shape sh)
    {
    int a;
    a = sh.area();
    Console.WriteLine("Area: {0}", a);
    }
    }
    class Tester
    {

    static void Main(string[] args)
    {
    Caller c = new Caller();
    Rectangle r = new Rectangle(10, 7);
    Triangle t = new Triangle(10, 5);
    c.CallArea(r);
    c.CallArea(t);
    Console.ReadKey();
    }
    }
    }

    When the above code is compiled and executed, it produces the following result:


    Output

    Rectangle class area:
    Area: 70
    Triangle class area:
    Area: 25