Полиморфизм (от греч. poly — много и morphe — форма) — один из главных столпов объектно-ориентированного программирования. Его суть заключается в том, что методы с одинаковой сигнатурой могут выполнять разные действия.
Например, все животные могут подать голос, у всех есть метод Voice, но для каждого конкретного вида животных голос звучит по своему.
Самое короткое определение полиморфизму дал Бьерн Страуструп и оно звучит так:
Один интерфейс, множество реализаций.
Конкретные реализации полиморфного поведения в коде делят на 3-и группы.
Add hoc полиморфизм — это полиморфизм, основанный на различении типов. Для различных типов аргументов используется разный код функции.
Один классический пример — это перегрузка (overloading) метода:
class C
{
public void f(int x) { Console.WriteLine("C.f(int)"); }
public void f(string x) { Console.WriteLine("C.f(string)"); }
}
Здесь имя f привязано к двум различным методам, и компилятор выбирает тот или иной метод в зависимости от типа аргумента. Это пример статического ad hoc-полиморфизма: типы должны быть известны на этапе компиляции, и компилятор точно знает, который из методов будет выполнен.
Другой пример ad hoc-полиморфизма — это переопределение (overriding) виртуального метода:
class B
{
public virtual void f(int x) { Console.WriteLine("B.f(int)"); }
}
class D : B
{
public override void f(int x) { Console.WriteLine("D.f(int)"); }
}
Здесь также происходит различение по типам, но на этот раз — по типу неявного нулевого аргумента this. Выбор переопределённого метода откладывается на момент выполнения; на момент компиляции компилятор точно не знает, какой из группы переопределённых методов будет выполнен. Это пример динамического ad hoc-полиморфизма.
Кроме того, есть ещё понятие параметрического полиморфизма: это ситуация, когда один и тот же метод работает с аргументами различных типов одинаково, не зависимо от их точного типа. Тривиальный пример для языков с наследованием (например, C#) — функция, работающая с объектом некоторого класса C, часто может без изменений работать с объектом порождённого от C класса (этот вид полиморфизма часто называют полиморфизм включения). Менее тривиальный пример — generic-методы, которые могут, в зависимости от generic-параметра, работать с разными типами объектов. Пример:
class Enumerable
{
public T First(this IEnumerable seq)
{
using (IEnumerator en = seq.GetEnumerator())
{
if (!en.MoveNext())
throw new InvalidOperationException();
return en.Current;
}
}
}
Ad-Hock Полиморфизм это
- Классический (Принудительный) полиморфизм т. е. Возможность динамической подмены типов (объектов) во время выполнения программы, но без второй формы Инкапсуляции т. е. без сокрытия реализации (Когда вы в классическом полиморфизме делаете upcast то происходит сокрытие свойств и методов из производного типа).
или
- Возможность обращаться с объектами у которых одинаковый интерфейс взаимодействия одинаковым образом
Пример:
class A{public void Method(){Console.WriteLine("A");}}
class B{public void Method(){Console.WriteLine("B");}}
class C{public void Method(){Console.WriteLine("C");}}
У этих классов нету базового класса но у них одинаковый интерфейс взаимодействия.
Ad hoc полиморфизм или (Полиморфизм для конкретного случая) позволяет обращаться схожим образом к объектам, не связанным классическим наследованием.
Пример:
// данный интерфейс создан для создания своего рода базового типа
// для классов А, B, и C у которых нету такового.
interface IInterface
{
void Method();
}
// в данном случае мы создаем новые классы обертки со схожими интерфейсами
// и с базовым типом
class MyA : A, IInterface { }
class MyB : B, IInterface { }
class MyC : C, IInterface { }
class Program
{
static void Main()
{
// тем самым мы работаем с классами как будто у них был базовый тип
// но без сокрытия реализации
IInterface instance = new MyA();
instance.Method();
instance = new MyB();
instance.Method();
instance = new MyC();
instance.Method();
}
}
