Приветствую всех! Сегодня поговорим о полиморфизме и рассмотрим ряд примеров и определений. А так же отличия полиморфизма от AdHoc полиморфизма.
Полиморфизм относится к способности определять множество классов функционально разными, но одинаково названными методами или свойствами, которые попеременно могут использоваться кодом клиента во время выполнения. О полиморфизме часто говорят как о третьем базовом элементе объектно-ориентированного программирования, после инкапсуляции и наследования. Полиформизм — это греческое слово, означающее «наличие многих форм». Это понятие имеет два различающихся аспекта:
- Во время выполнения объекты производного класса могут рассматриваться как объекты базового класса в таких местах как параметры метода и коллекции массивов. При этом объявленный тип объекта больше не идентичен его типу времени выполнения.
- Базовые классы могут определять и реализовывать виртуальные методы, а производные классы могут переопределять их. Это означает, что они предоставляют свои собственные определение и реализацию. Во время выполнения, когда клиентский код вызывает метод, среда CLR ищет тип времени выполнения объекта и вызывает это переопределение виртуального метода. Таким образом, в исходном коде можно вызвать метод в базовом классе и вызвать выполнение метода с версией производного класса.
Если производный класс наследует от базового класса, то он приобретает все методы, поля, свойства и события базового класса. Проектировщик производного класса может выбирать из следующих возможностей:
- переопределить виртуальные члены в базовом классе
- наследовать самый близкий метод базового класса без его переопределения
- определить новую не виртуальную реализацию этих членов, которая скрывает реализации базового класса.
Производный класс может переопределить член базового класса, если только член базового класса объявлен как виртуальный или абстрактный. Производный член должен использовать ключевое слово override, чтобы явно указать, что метод должен участвовать в виртуальном вызове.
Функции языка C# позволяют обеспечить и поддерживать обратную совместимость за счет управления версиями между базовыми и производными классами в различных
библиотеках. Это означает, например, что если в базовом классе будет создан новый член, имя которого совпадает с именем члена в производном классе, язык C# обработает такую ситуацию, и она не приведет к непредвиденным результатам. Это также означает, что в классе должно быть явно указано, будет ли метод переопределять наследуемый метод, или это новый метод, который будет скрывать наследуемый метод с тем же именем.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
public class MyClass1 { public virtual void Method() { Console.WriteLine("1"); } } public class MyClass2:MyClass1 { public override void Method() { Console.WriteLine("2"); } } class Program { static void Main(string[] args) { MyClass1 my = new MyClass2(); my.Method(); Console.ReadKey(); } } //2 |
В C# производный класс может включать методы с теми же именами, что и у методов базового класса:
Метод базового класса может быть определен как виртуальный.
- Если перед методом в производном классе не указано ключевое слово new или override, компилятор выдаст предупреждение, и обработка метода будет производиться как в случае наличия ключевого слова new.
- Если перед методом в производном классе указано ключевое слово new, то этот метод определен как независимый от метода в базовом классе.
- Если перед методом в производном классе указано ключевое слово override, то объекты производного класса будут вызывать этот метод вместо метода базового класса.
- Базовый метод можно вызвать из производного класса с помощью ключевого слова base.
- Ключевые слова override, virtual и new могут также применяться к свойствам, индексам и событиям.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
public class MyClass1 { public virtual void Method() { Console.WriteLine("1"); } } public class MyClass2:MyClass1 { public new void Method() { Console.WriteLine("2"); } } class Program { static void Main(string[] args) { MyClass1 my = new MyClass2(); my.Method(); Console.ReadKey(); } } //1 |
Существует две основные разновидности полиморфизма: классический полиморфизм и полиморфизм «для конкретного случая» или же ad hoc полиморфизм.
Ad hoc полиморфизм позволяет обращаться схожим образом к объектам, не связанным классическим наследованием. Достигается это очень просто: в каждом из таких
объектов должен быть метод с одинаковой сигнатурой (то есть одинаковым именем метода, принимаемыми параметрами и типом возвращаемого значения). В языках, поддерживающих такой тип полиморфизма, применяется технология позднего связывания, когда тип объекта, к которому происходит обращение, становится ясен только в процессе выполнения программы.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
interface IInterface { void Method(); } //Just for fun! class MyClass1 : Class1, IInterface { } class MyClass2 : Class2, IInterface { } class MyClass3 : Class3, IInterface { } class Program { static void Main() { IInterface[] array = { new MyClass1(), new MyClass2(), new MyClass3() }; for (var i = 0; i < 3; i++) array[i].Method(); // Delay. Console.ReadKey(); } } |