Слово полиморфизм означает иметь много форм. В объектно-ориентированном программировании полиморфизмом часто понимается как "один интерфейс, множество функций".
Полиморфизм может быть статическим или динамическим. В статическом полиморфизме выбор определяется во время компиляции. В динамическом полиморфизме выбор определяется во время выполнения.
Механизм связывания функции с объектом во время компиляции называется ранним связыванием. Он также называется статическое связывание. C# использует два механизма для реализации статического полиморфизма. Это:
Вы можете иметь несколько определений для одного имени метода в одной области видимости. Определенные методы должны отличаться друг от друга по видам и/или количеству аргументов в списке аргументов. Нельзя перегрузить объявление методов, которые отличаются только типом возвращаемого значения.
Ниже приведен пример, в котором те же методы print() используются для печати различных типов данных:
using System;
namespace PolymorphismApplication
{
class Printdata
{
void print(int i)
{
Console.WriteLine("Вывод int: {0}", i );
}
void print(double f)
{
Console.WriteLine("Вывод float: {0}" , f);
}
void print(string s)
{
Console.WriteLine("Вывод string: {0}", s);
}
static void Main(string[] args)
{
Printdata p = new Printdata();
// вызов метода print для вывода integer
p.print(5);
// вызов метода print для вывода float
p.print(500.263);
// вызов метода print для вывода string
p.print("Привет C#");
Console.ReadKey();
}
}
}
Если приведенный выше код скомпилировать и выполнить, это приведет к следующему результату:
Вывод int: 5
Вывод float: 500.263
Вывод string: Привет C#
C# позволяет создавать абстрактные классы, которые используются для обеспечения частичной реализации интерфейса. Реализация завершается, когда производный класс наследует от него. Абстрактные классы содержат абстрактные методы, которые осуществляются в производном классе. Производные классы имеют более специализированные функциональные возможности.
Обратите внимание на следующие правила об абстрактных классах:
Следующая программа демонстрирует абстрактный класс:
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("Площадь прямоугольника :");
return (width * length);
}
}
class RectangleTester
{
static void Main(string[] args)
{
Rectangle r = new Rectangle(10, 7);
double a = r.area();
Console.WriteLine("Площадь: {0}",a);
Console.ReadKey();
}
}
}
Если приведенный выше код скомпилировать и выполнить, это приведет к следующему результату:
Площадь прямоугольника :
Площадь: 70
Если у вас есть метод, определенный в классе, который вы хотите реализовать в унаследованном классе, вы используете виртуальный метод. Виртуальные методы могут быть реализованы по-разному в разных унаследованных классах и вызов этих методов будет решаться во время выполнения.
Динамический полиморфизм реализуется абстрактными классами и виртуальными методами.
Следующая программа демонстрирует это:
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("Площадь родительского класса :");
return 0;
}
}
class Rectangle: Shape
{
public Rectangle( int a=0, int b=0): base(a, b)
{
}
public override int area ()
{
Console.WriteLine("Площадь класса Rectangle :");
return (width * height);
}
}
class Triangle: Shape
{
public Triangle(int a = 0, int b = 0): base(a, b)
{
}
public override int area()
{
Console.WriteLine("Площадь класса Triangle :");
return (width * height / 2);
}
}
class Caller
{
public void CallArea(Shape sh)
{
int a;
a = sh.area();
Console.WriteLine("Площадь: {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();
}
}
}
Если приведенный выше код скомпилировать и выполнить, это приведет к следующему результату:
Площадь класса Rectangle:
Площадь: 70
Площадь класса Triangle:
Площадь: 25