Студопедия КАТЕГОРИИ: АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция |
Наследование и переопределение. Принцип конструирования программ
ООП позволяет определить новый объект как потомок (наследник) другого, ранее определенного типа. Это означает, что новый тип автоматически получает все поля и методы ранее определенного типа, который в этом случае называется предком или родителем. В объявлении типа-потомка (наследника) должно быть указано в круглых скобках после служебного слова object имя родительского типа. Поля и методы предка могут появляться в телах методов наследников так, как если бы они были явно объявлены в объектах-наследниках. Это существенно упрощает запись схожих объектов. Форма объявления объекта-потомка (наследника): TYPE Имя-типа-объекта-потомка =OBJECT(Имя-типа-объекта-предка) Новые-поля-объекта-потомка; Новые-методы-объекта-потомка; END; Предок у типа может быть только один. Он может быть потомком другого типа и т. д. Потомков у одного предка может быть много. Потомок наследует поля и методы всех своих предков. Процесс наследования является транзитивным: если тип объекта ТуреВ -наследник типа ТуреА, а тип ТуреС - наследник типа ТуреВ, то тип объекта ТуреС также является наследником ТуреА: Туре А------------ →Туре В →Туре С В потомках (производных, дочерних) нельзя объявлять идентификаторы полей, определенные в одном из типов предка. На методы это ограничение не распространяется. Объект-потомок может переопределить любой из методов, наследуемый от предков. Метод, переопределенный в типе-потомке, имеет то же имя и может иметь другие параметры. Переопределенный метод переходит ко всем последующим потомкам иерархии. Для каждого потомка действует метод, определенный в нем самом или в ближайшем объекте-предке, если в данном объекте этот метод не переопределен. Пример простой иерархической структуры приведен на рис. 1. Наследование - самое мощное свойство ООП. Оно позволяет строить библиотеку по принципу "от простого к сложному". Такой принцип разработки программ называется восходящим программированием. Ввод с помощью наследования нового объекта в библиотеку позволяет максимально использовать ранее созданные объекты. При использовании ООП рекомендуется сочетание двух принципов конструирования программ: нисходящего и восходящего программирования. Методами нисходящего программирования генеральный алгоритм расчленяется на ряд относительно крупных и законченных в смысловом отношении фрагментов (модулей). А реализация этих фрагментов может производиться с использованием ООП. Основное применение ООП - это разработка библиотек определенного направления. Примером такого применения является VCL - Visual Component Library - библиотека компонентов системы визуального программирования Delphi. Рис. 1 Пример простой иерархической структуры Наследование имеет определенные правила совместимости типов объектов. При этом производный тип (тип-потомок) совместим по типу со своим предком: - между экземплярами объекта; - между указателями на экземпляры объектов; - между формальными и фактическими параметрами. Совместимость имеет место только от потомка к предку. Другими словами, производные типы можно использовать вместо родительских, но не наоборот. Это определяет правила присваивания для переменных типа объект. Они состоят в том, что переменным можно присваивать значения этого же типа и любого производного от него, т. е. предку можно присвоить значение объекта-потомка. Обратное присваивание недопустимо. Производный тип всегда получается не меньшим, чем тип предка (родительский). В результате выполнения присваивания будут скопированы от источника только те поля, которые являются общими для обоих типов. Полиморфизм Основные понятия Полиморфизм - это возможность иметь несколько методов с одним и тем же именем для различных объектов одной иерархии, т. е. средство для развития объектов в потомках. Оно реализуется тем, что объект-потомок может переопределять, т. е. заменять методы предка на новые с теми же именами. Какой из методов будет выполняться при. обращении к методу с заданным именем, определяется типом объекта (предок или потомок) и используемого метода. Методы объектов по способам их переопределения могут быть статические, виртуальные и динамические (подкласс виртуальных). В соответствии с этим процесс установки взаимосвязи объектов и методов может быть: - ранним - во время компиляции - для статических методов; - поздним - во время выполнения программы (вызова метода) для виртуаль Статические методы По умолчанию все методы статические. Все ранее рассмотренные методы -статические. Такое наименование методов связано с тем, что определение и размещение ссылок на них (для вызова методов) производится на этапе компиляции и на все время выполнения программы. Это - раннее связывание. Список формальных параметров статических методов может быть различным у метода предка и методов потомков, переопределяющих (заменяющих) этот метод предка. Со статическим методом связан способ наследования. Если в объявлении потомка появляется метод с тем же именем, что и у предка, то в этом типе и во всех его потомках этот метод будет переопределен. Таким образом, потомки могут использовать переопределенные ими методы предка. Предок может вызвать только свои методы; методы потомков для него недоступны. Таким образом, при использовании статических методов полиморфизм распространяется от текущего уровня иерархии вниз, к потомкам. Действия компилятора при обработке методов иерархии объектов для статических методов: 1) при вызове метода компилятор устанавливает тип объекта, вызывающего 2) затем он ищет метод в пределах этого типа; найдя его, компилятор назначает вызов этого метода; 3) если метод не найден, то компилятор рассматривает тип непосредственно а) если метод с таким именем найден, формируется вызов метода этого б) если метод не найден в типе ближайшего предка, компилятор переходит в) если компилятор, дойдя до верхнего уровня иерархии, не найдет метод, Field identifier expected - ожидается идентификатор поля. Это сообщение выдается, если идентификатор не соответствует имени поля переменной типа RECORD или типа OBJECT. Существенное ограничение статических методов: если метод предка вызывает другие методы, то это могут быть только методы предка, даже если потомок имеет свои собственные методы с таким же именем метода. Этот недостаток предопределен тем, что связь объекта с методом производилась на этапе компиляции, статически, на все время выполнения программы. Этот недостаток статических методов устраняется использованием виртуальных методов. Ограничение статических методов рассмотрим на примере программы листинга 3. Из него видно существенное ограничение статических методов: если метод (Metl объекта ObjName1) предка вызывает другие методы (Met2), то это могут быть только методы предка (objNamel .Met2), даже если потомок имеет свои собственные методы с таким же именем метода (objName2 .Met2). В примере листинга 3 оператор V2.Metl; вызывает выполнение метода ObjNamel .Metl, который вызывает метод ObjNamel .Met2, несмотря на то что тип ObjName2 имеет свой собственный метод ObjName2 .Met2. Это происходит потому что связь объекта с методом производилась на этапе компиляции. Схематично это представлено на рис. 2. Листинг 3.Вызовы статических методов предка и потомка. Program novirt1; Uses Crt; Type ObjName1 = object { - объявление объекта-предка } Fl1 : integer; { - поле } Procedure Met1; { - методы } Procedure Met2; End; ObjName2 = object (ObjName1) { - объявление потомка } Procedure Met2; { - замена статического метода } End; { --- Методы объекта ObjName1 ------- } Procedure ObjName1.Met1; Begin Met2; { - вызов только метода ObjName1.Met2 !!} End; Procedure ObjName1.Met2; Begin FL1 := 12; Writeln ( 'Работает метод ObjName1.Met2: FL1 = ', FL1) End; { ----- Метод объекта ObjName2 ------ } Procedure ObjName2.Met2; Begin FL1 := 34; Writeln ( 'Работает метод ObjName2.Met2: FL1 = ', FL1) End; Var VI:ObjName1; { - переменная объектного типа - предка } {--------- - Основная программа } Begin ClrScr; Assign (Output, 'Inovirt.res'); Rewrite (Output); Writeln ( 'ОБЪЕКТЫ, СТАТИЧЕСКИЕ МЕТОДЫ1 ); Writeln ('Работаем с VI - экземпляром типа предка'); VI.Met1; {- вызывается метод Met1 для экземпляра VI - предка } { Met1 вызывает метод ObjName1.Met2 - предка } V1.Met2; { - непосредственно вызывается метод ObjName1.Met2; } Writeln ('Работаем с V2 - экземпляром типа потомка'); V2.Met1; { - вызывается метод Met1 для экземпляра V2 - потомка; Met1 вызывает метод ObjName1.Met2 - предка, а не ObjName2.Met2 - потомка - в этом - ограничение } V2.Met2 { - непосредственно вызывается метод ObjName2.Met2; } Close (Output); End. Рис. 2 Схема ограничения вызова переопределенных статических методов |
||
Последнее изменение этой страницы: 2018-05-10; просмотров: 207. stydopedya.ru не претендует на авторское право материалов, которые вылажены, но предоставляет бесплатный доступ к ним. В случае нарушения авторского права или персональных данных напишите сюда... |