Csharp Polymorphism
# C# Polymorphism
Polymorphism is the ability of one interface to be used for a general class of actions.
**Polymorphism** means "many forms". In object-oriented programming paradigms, polymorphism often manifests as "one interface, multiple functions".
Polymorphism can be static or dynamic. In **static polymorphism**, the response to a function is determined at compile time. In **dynamic polymorphism**, the response to a function is determined at runtime.
In C#, every type is polymorphic because all types, including user-defined types, inherit from Object.
Polymorphism is the same interface, using different instances to perform different operations, as shown in the figure:
!(#)
> In reality, for example, the action of pressing the F1 key:
>
>
> * If you are currently in the Flash interface, the AS 3 help documentation will pop up;
> * If you are currently in Word, the Word help will pop up;
> * In Windows, the Windows help and support will pop up.
>
>
> The same event occurring on different objects produces different results.
## Static Polymorphism
At compile time, the mechanism that links a function to an object is known as early binding, also called static binding. C# provides two techniques to implement static polymorphism. They are:
* Function Overloading
* Operator Overloading
Operator overloading will be discussed in the next chapter. Next, we will discuss function overloading.
* * *
## Function Overloading
You can have multiple definitions of the same function name within the same scope. The function definitions must differ from each other by the parameter list, either in the types of parameters or in the number of parameters. Different overloads are function declarations that differ only in their return type.
The following example demonstrates several functions with the same name **Add()**, used to add different numbers of parameters:
## Example
using System;
namespace PolymorphismApplication
{
public class TestData
{
public int Add(int a, int b, int c)
{
return a + b + c;
}
public int Add(int a, int b)
{
return a + b;
}
}
class Program
{
static void Main(string[] args)
{
TestData dataClass =new TestData();
int add1 = dataClass.Add(1, 2);
int add2 = dataClass.Add(1, 2, 3);
Console.WriteLine("add1 :"+ add1);
Console.WriteLine("add2 :"+ add2);
}
}
}
The following example demonstrates several functions with the same name **print()**, used to print different data types:
## Example
using System;
namespace PolymorphismApplication
{
class Printdata
{
void print(int i)
{
Console.WriteLine("Printing integer: {0}", i );
}
void print(double f)
{
Console.WriteLine("Printing float: {0}" , f);
}
void print(string s)
{
Console.WriteLine("Printing string: {0}", s);
}
static void Main(string[] args)
{
Printdata p =new Printdata();
// Call print to print integer
p.print(1);
// Call print to print float
p.print(1.23);
// Call print to print string
p.print("Hello ");
Console.ReadKey();
}
}
}
When the above code is compiled and executed, it produces the following result:
Printing integer: 1Printing float: 1.23Printing string: Hello
* * *
## Dynamic Polymorphism
C# allows you to create abstract classes using the keyword **abstract** to provide partial implementation of an interface. When a derived class inherits from this abstract class, the implementation is completed. **Abstract classes** contain abstract methods, which can be implemented by derived classes. Derived classes have more specialized functionality.
Please note the following rules regarding abstract classes:
* You cannot create an instance of an abstract class.
* You cannot declare an abstract method outside an abstract class.
* A class can be declared as **sealed** by placing the keyword **sealed** before the class definition. When a class is declared as **sealed**, it cannot be inherited. Abstract classes cannot be declared as sealed.
The following program demonstrates an abstract class:
## Example
using System;
namespace PolymorphismApplication
{
abstract class Shape
{
abstract public 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:
Rectangle class area:Area: 70
When a function defined in a class needs to be implemented in an inheriting class, you can use a **virtual method**.
Virtual methods are declared using the keyword **virtual**.
Virtual methods can have different implementations in different inheriting classes.
The call to a virtual method is resolved at runtime.
Dynamic polymorphism is implemented through **abstract classes** and **virtual methods**.
The following example creates a Shape base class and derived classes Circle, Rectangle, and Triangle. The Shape class provides a virtual method named Draw, which is overridden in each derived class to draw the specified shape for that class.
## Example
using System;
using System.Collections.Generic;
public class Shape
{
public int X {get;private set;}
public int Y {get;private set;}
public int Height {get;set;}
public int Width {get;set;}
// Virtual method
public virtual void Draw()
{
Console.WriteLine("Performing base class drawing tasks");
}
}
class Circle : Shape
{
public override void Draw()
{
Console.WriteLine("Drawing a circle");
base.Draw();
}
}
class Rectangle : Shape
{
public override void Draw()
{
Console.WriteLine("Drawing a rectangle");
base.Draw();
}
}
class Triangle : Shape
{
public override void Draw()
{
Console.WriteLine("Drawing a triangle");
base.Draw();
}
}
class Program
{
static void Main(string[] args)
{
// Create a List object and add Circle, Triangle, and Rectangle to it
var shapes =new List
{
new Rectangle(),
new Triangle(),
new Circle()
};
// Use a foreach loop to iterate through the list of derived classes and call the Draw method on each Shape object
foreach(var shape in shapes)
{
shape.Draw();
}
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
When the above code is compiled and executed, it produces the following result:
Drawing a rectanglePerforming base class drawing tasksDrawing a trianglePerforming base class drawing tasksDrawing a circlePerforming base class drawing tasksPress any key to exit.
The following program demonstrates calculating the area of different shape images using the virtual method area():
## 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:
Rectangle class area:Area:70Triangle class area:Area:25
YouTip