Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Особенностью ООП является то.doc
Скачиваний:
30
Добавлен:
09.02.2015
Размер:
467.97 Кб
Скачать

Наследование при разработке классов

В ООП существует возможность конструирования новых более сложных классов из уже имеющихся посредством добавления полей и определения новых методов (принцип иерархичности). При этом исходный класс, на базе которого выполняется конструирование, часто называется родителем, а производный -потомком. Специальный механизм наследования обеспечивает классу-потомку возможность использования полей и методов одного или нескольких родительских классов.

Если непосредственный родитель единственный, то наследование называетсяпростымнаследованием, а если таких классов несколько – томножественным наследованием. При этом класс родитель (или классы родители) и класс потомок образуют иерархию (рис.).

Наличие механизма наследования в языке программирования позволяет повторно не определять в классе уже описанные параметры и свойства объектов, производный класс их просто «наследует».

ПримерНаследование (класс Окно_меняющее_цвет). Построим на базе класса Окно класс-потомок, который может изменять цвет окна на экране. Для этого к родительскому классу достаточно добавить метод «Изменить цвет»:

Класс Окно_меняющее_цвет - родитель: класс Окно:

метод Изменить цвет (Соlоr);

Конец описания.

Класс «Окно_меняющее_цвет» содержит все поля родительского класса и все его методы. Дополнительно объекты типа «Окно_меняющее_цвет» могут менять цвет окна на указанный в сообщении «Изменить_цвет» (рис.).

При множественном наследовании наследуются поля и методы всех родителей. В том случае, если среди родителей есть классы, принадлежащие одной иерархии, происходит дублирование полей и методов, наследуемых от общих родителей. Для того чтобы избежать неоднозначности, например в C++, введено понятие виртуального наследования, при использовании которого виртуально наследуемые поля и методы не дублируются.

Таким образом, в иерархическом дереве классов по мере удаления от корня мы встречает все более сложные классы, экземплярами которых будут объекты с более сложной структурой и поведением.

Наследование свойств в иерархии существенно упрощает работу программиста. В настоящее время созданы библиотеки наиболее часто встречающихся классов, которые можно использовать вновь и вновь, строя на их основе классы для решения различных задач.

Полиморфизм при разработке классов

Простой полиморфизм

При создании иерархии классов может обнаружиться, что некоторые свойства объектов, сохраняя название, изменяются по сути.

Для реализации таких иерархий в языке программирования должен быть предусмотрен полиморфизм, обеспечивающий возможность задания различ­ных реализаций некоторого единого по названию метода для классов различных уровней иерархии. В ООП такой полиморфизм называетсяпростым, а методы, имеющие одинаковое название -статическими полиморфными. Совокупность полиморфных методов с одним именем для иерархии классов образуетеди­ный полиморфный метод иерархии, в котором реализация полиморфного метода для конкретного класса представляет отдельный аспект.

Термин «полиморфизм» в программировании, в соответствии со своим изначальным смыслом («многообразие»), используется для обозначения встроенного механизма определения соответствия мода функции типу параметров. Такой механизм реализуется не только в средствах ООП.

Различают несколько терминов, связанных с конкретными механизмами реализации полиморфизма для различных случаев:

  • чистый полиморфизм- используется для обозначения того, что один код функции может по-разному интерпретироваться в зависимости от типа аргументов; используется в языках высокого уровня абстракции, например, в языке LISP или SMALLTALK;

  • перегрузка {полиморфные имена функций) - используется, когда определяется несколько функций с одним именем - одно и то же имя функции может многократно использоваться в разных местах программы; выбор нужной функции может определять типами аргументов, областью видимости (внутри модуля, файла, класса и т.д.); если выбор определяется типом аргументов, топерегрузка называется параметрической; (например, язык C++ позволяет разработчику выполнять параметрическую перегрузку функций вне классов);

  • переопределение(простой полиморфизм) - используется в ООП при наличии различных определений методов в иерархии классов, конкретный метод определяется типом объекта при компиляции программы –раннее связывание, методы называютсястатическими полиморфными;

  • полиморфные объекты(сложный полиморфизм) - используются в ООП при наличии различных определений методов в иерархии классов - конкретный метод также определяется типом объекта, но в процессе выполнения программы –позднее связывание, методы называютсявиртуальными полиморфными(рассмотрены далее);

  • обобщенные функции или шаблоны- используются в ООП при реализации в языке параметризованных классов (например, в C++), параметрами такого класса являются типы аргументов методов класса (рассмотрены далее).

Пример

Простой полиморфизм(класс Окно_с_текстом). Пусть необходимо разработать на базе класса «Окно» класс «Окно_с_текстом». Для этого к полям класса «Окно» необходимо добавить специальные поля для определения координат первой буквы текста - Xt, Yt и поле, содержащее сам текст - Text. Кроме этого, понадобится специальный метод, который будет обрабатывать сообщение «Нарисовать». Однако у нас уже существует родительский метод «Изобразить», который обрабатывает это сообщение. Следовательно, необходимо заменить родительский метод методом потомка. Механизм полиморфизма позволяет для класса-потомка «Окно_с_текстом» предусмотреть собственный метод «Изобразить» (рис.).

Метод «Инициализировать» также должен быть переопределен, так как он должен инициализировать дополнительные поля класса.

Класс Окно_с_текстом – родитель: класс Окно:

поля Xt, Yt, Text

метод Инициализировать (aXl,aYl,aX2,aY2,aColor,aXt, aYt, aText)

метод Изобразить

Конец описания.

Примечание. При реализации методов «Изобразить» и «Инициализировать» потомка можно вызвать соответствующие родительские методы, а затем добавить операторы, определяющие собственные действия метода для разрабатываемого класса.

Сложный полиморфизм или создание полиморфных объектов.

Полиморфными объектами или полиморфными переменными называются переменные, которым в процессе выполнения программы может быть присвоено значение, тип которого отличается от типа переменной. В языках с жесткой типизацией такая ситуация может возникнуть:

  • при передаче объекта типа класс-потомка в качестве фактического параметра подпрограмме, в которой этот параметр описан как параметр типа класса-родителя (явно - в списке параметров или неявно - в качестве внутреннего параметра, используемого при вызове методов - self или this);

  • при работе с указателями, когда указателю на объект класса-родителя присваивается адрес объекта класса-потомка.

В принципе, в обоих случаях речь идет об одной и той же ситуации: во внутреннем представлении в любом из указанных случаев используются адреса объектов.

Тип полиморфного объекта становится известным только на этапе выполнения программы.Соответственно, при вызове полиморфного метода для такого объекта нужный аспект также должен определяться на этапе выполнения. Для этого в языке должен бытьреализован механизм позднего связывания, позволяющий определять тип объекта и, соответственно, аспект полиморфного метода, к которому идет обращение в программе, на этапе ее выполнения.

С помощью механизма позднего связывания реализуетсяоперативная перестройка программы в соответствии с типами используемых объектов.

Пример

Сложный полиморфизм. Пусть родительский класс содержит два метода «Out» и «Print», один из которых вызывает другой. Класс-потомок наследует метод «Out», но имеет собственный метод «Print». Метод «Out» наследуется и может быть вызван как для объекта класса-родителя, так и для объекта класса-потомка (рис.).

При вызове метода «Out» для объекта класса-потомка необходимо обеспечить, чтобы этот метод вызывал методPrintпотомка, а не родителя (рис.).

Определить, для объекта какого класса: родителя или потомка вызывается метод «Out», можно только на этапе выполнения. Следовательно, для метода «Print» необходимо обеспечить позднее связывание.

Если определение адреса метода «Print» происходило бы на этапе компиляции программы, то и для объекта родительского класса, и для объекта класса-потомка из метода «Out» вызывался бы метод «Print» класса-родителя. Описание метода «Print» как метода, для которого запрещается определение адреса на этапе компиляции, приведет к тому, что адрес метода «Print» будет определяться в процессе выполнения программы. В этот момент уже будет известно, объект какого класса вызывает метод «Out», и будет вызываться метод «Print» именно этого класса.

Методы, для которых должно реализовываться позднее связывание, получили название виртуальных. Для их описания в рассматриваемых далее языках программирования используется служебное слово «virtual».

Следует отметить, что методы, работающие с полиморфными объектами – это всегда методы классов-родителей, описывающие общие моменты поведения объектов. В сложной иерархии, таким образом, можно выделить семейство классов со схожим поведением объектов. Они образуют поддерево, в корне которого находится класс, определяющий общие моменты поведения.

Реализация механизма позднего связывания осуществляетсяс использованием специальной таблицы, получившей название таблицы виртуальных методов (ТВМ). ТВМ создается для каждого класса, имеющего собственные или наследующего виртуальные методы. Она содержит адреса виртуальных методов (рис.). Объекты таких классов содержат адрес ТВМ своего класса. При вызове виртуального метода для объекта происходит обращение к ТВМ класса, по которой и определяется требуемый метод.

При использовании полиморфных объектов возникают проблемыс доступом к полям объекта, описанным в классе-потомке: указатель на объект класса-родителя связан с описанием полей класса-родителя, и поля, описанные в классе-потомке, для него «невидимы» (рис.).

В таких случаях приходится средствами используемого языка явно переопределять тип объекта.

Группа 14