Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекция 2. Наследование.doc
Скачиваний:
5
Добавлен:
15.11.2019
Размер:
273.92 Кб
Скачать

Полиморфизм: классический и для конкретного случая

Последний, третий столп объектно-ориентированного программирования — это полиморфизм. Можно сказать, что этот термин определяет возможности, заложенные в языке, по интерпретации связанных объектов одинаковым образом. Существует две основные разновидности полиморфизма: классический полиморфизм и полиморфизм «для конкретного случая» (ad hoc). Классический полиморфизм встречается только в тех языках, которые поддерживают классическое наследование (в том числе, конечно, и в С#). При классическом полиморфизме вы можете определить в базовом классе набор членов, которые могут быть замещены в производном классе. При замещении в производных классах членов базового класса эти производные классы будут по-разному реагировать на одни и те же обращения.

Для примера мы вновь обратимся к нашей иерархии геометрических фигур. Предположим, что в классе Shape (геометрическая фигура) определена функция Draw( ) — рисование, которая не принимает параметров и ничего не возвращает Поскольку геометрические фигуры бывают разными и каждый тип фигуры потребуется изображать своим собственным уникальным способом, скорее всего, нам потребуется в производных классах (таких как Hexagon — шестиугольник и Circle — окружность) создать свой собственный метод Draw( ), заместив им метод Draw( ) базового класса (рис. 3.5).

Рис. 3.5. Классический полиморфизм

Классический полиморфизм позволяет определять возможности всех производных классов при создании базового класса. Например, в нашем примере вы можете быть уверены, что метод Draw( ) в том или ином варианте присутствует в любом классе, производном от Shape. К достоинствам классического полиморфизма можно отнести также и то, что во многих ситуациях вы сможете избежать создания повторяющихся методов для выполнения схожих операций (типа DrawCircle( ), DrawRectangleO, DrawHexagon( )и т. д.).

Вторая разновидность полиморфизма — полиморфизм для конкретного случая (ad hoc polymorphism). Этот тип полиморфизма позволяет обращаться схожим образом к объектам, не связанным классическим наследованием. Достигается это очень просто: в каждом из таких объектов должен быть метод с одинаковой сигнатурой (то есть одинаковым именем метода, принимаемыми параметрами и типом возвращаемого значения. В языках, поддерживающих полиморфизм этого типа, применяется технология «позднего связывания» (late binding), когда тип объекта, к которому происходит обращение, становится ясен только в процессе выполнения программы. В зависимости от того, к какому типу мы обращаемся, вызывается нужный метод. В качестве примера рассмотрим схему на рис. 3.6.

Обратите внимание, что общего предка — базового класса для ССircle, СНехаgon и CRectangle не существует. Однако в каждом классе предусмотрен метод Draw( ) с одинаковой сигнатурой. Для того чтобы продемонстрировать применение полиморфизма этого типа в реальном коде, мы воспользуемся примером на Visual Basic 6.0. До изобретения VB.NET Visual Basic не поддерживал классический полиморфизм (так же, как и классическое наследование), заставляя разработчиков сосредоточивать свои усилия на полиморфизме ad hoc.

Рис. 3.6. Полиморфизм для конкретного случая

‘ Это - код на Visual Basic 6.0!

‘ Вначале создадим массив элементов типа Object и установим для каждого элемента ссылку на объект

Dim objArr(3) as Object

Set objArr(0) = New Ccircle

Set objArr(1) = New Chexagon

Set objArr(2) = New Ccircle

Set objArr(3) = New Crectangle

' Теперь с помощью цикла заставим каждый элемент нарисовать самого себя

Dim i as Integer

For i = 0 to 3

objArr(i). Draw () 'Позднее связывание

Next i

В этом коде мы вначале создали массив элементов типа Object (это встроенный тип данных Visual Basic 6.0 для хранения ссылок на любые объекты, не имеющий ничего общего с классом System.Object в .NET). Затем мы связали каждый элемент массива с объектом соответствующего типа, а потом при помощи цикла воспользовались методом Draw( ) для каждого из этих объектов. Обратите внимание, что у геометрических фигур — элементов массива — нет общего базового класса с реализацией метода Draw( ) по умолчанию.

Теоретический обзор главных принципов полиморфизма — инкапсуляции, наследования и полиморфизма на этом закончен. Конечно же, в С# реализованы все эти принципы, при этом С# поддерживает и отношения «быть» и отношения «иметь» для повторного использования кода, и обе разновидности полиморфизма. Теперь наша задача — узнать, как реализуется каждый из этих принципов средствами синтаксиса С#.