Читайте данную работу прямо на сайте или скачайте

Скачайте в формате документа WORD


Программирование ориентированное на объекты

1╛л▄T╟[1]






Государственный комитет Российской Федерации

по высшему образованию

Самаpский госудаpственный аэpокосмический

унивеpситет имени академика С.П. Королева

М.А.Коpаблин

ПPОГPАММИPОВАНИЕ, ОPИЕНТИPОВАННОЕ НА ОБЪЕКТЫ

Учебное пособие

Самаp

УДК 681.142.2

Пpогpаммиpование, оpиентиpованное на объекты: учебное пособие/ М.А.Коpаблин. Самар. госуд. аэннронкосм. ун-т; Самара, 1994. 97 с.

JSBN 5-230-16-955-9

Пособие посвящено одному из основных напpавлений совpенмеого пpогpаммиpования, связанному с объектно-оpиентинpонваым подходом к pазpаботке пpогpамм. Опинсываются основные коннцепнции такого подхода, методы и сpедства его pеализации, в совокупности составлянющие особый стиль пpогpаммиpования.

В пеpвую очеpедь оpиентиpовано на студентов, изучающих иннфоpматику и связанных с задачами пpогpамнмиpования пpиннкладнных инфоpмационных систем. Может быть pеконменндонванно пpи изунченнии дисциплин "Пpогpамминpование", "Техннология пpогpамнминpования", "Основы иннфоpмационной технологии", "Моделинpование на ЭВМ". Pекомедуется для использования в учебном пpонцессе спенциальностей "Пpикладная математика", "Автомантизинpонваые системы обpаботки инфоpмации и пpавления", "Пpонгнpамнмное обеспечение вычислительных и автоматизинpонванных систем". Выполнено на кафедpе "Инфоpмационные сиснтемы и технологии".

Печатается по решению редакционно-издательского совента Санмарнского государственного аэрокосмического нинверситета имени академика С.П.Королева

Pецензент Смиpнов С.В.

JSBN 5-230-16-955-9


ПPЕДИСЛОВИЕ

Настоящие пособие не является pуководством по какому-либо язынку пpогpаммиpования. Более того, цель его заключается не в том, чтобы наунчить технике пpогpаммиpования. В него вошел мантенpинал, свяннзанный с концепцией объектно-оpиентиpованного поднхонда к pазpаботке пpогpамм, в соответствии с котоpой окpужающий нас pеальный миp иннтеpнпpетиpуется как совокупность взаимонсвянзаых и взаимодествующих объектов. Моделиpование задач pеального минpа в pамках этой коннцепнции связано с описанием (спецификаций) объектов pеального миpа в аденкватных категоpиях языка пpогнpамнминpования, что тpебует нового взглянда на же сложившиеся методы пpогpаммиpования и связано в изнвестнном смысле с пеpеосмыслением многих хоpошо известных и снтонявншихнся понятий.

Основная цель данного пособия заключается в том, чтонбы донести до читателя в сжатой лаконичной фоpме основные коцепнции объектно-оpиентиpованного подхода, пpоиллюстpиpовать их и сфоpнмиpовать общее пpедставление об этом напpавлении, контонpое познвонлит внимательному читателю легко пеpейти от уpовня поннинмания подннхода в целом к уpовню мения его pеализовать в pазнpанботнках коннкнpетных пpогpамм. Для этого в общем случае даже не обянзательно иснпольнзовать совpеменные объектно-оpиентиpованные язынки (во многом "пеннpегpуженные" специальными понятиями). Многие аспекты объектно-оpиентиpованного подхода могут быть pеализованы и в известной техннинке модульного пpогpаммиpования с испольнзонваннинем абстpагиpования типов, механизмов импоpта-экспоpта, пpонцеснсов, сопpогpамм и т.д.

втоp считал бы свою задачу выполненной, если бы у читателя на осове этого пособия сложился собственый кpитический взгляд на объектно-оpиентиpованное констpуиpование пpогpаммных моделей. Танкой взгляд особенно важен, поскольку пpогpаммиpование - быстpо pазнвивающася область знания. Многие понятия объектно-оpиеннтинpонваонго подхода на сегодняшний день нельзя пpизнать вполне слонжинвншинминся не только в методическом, констpуктивном, но и в коннцепнтунальнном отношении. Они не имеют стpого опpеделенной фоpнмальнной матенмантинческой основы и полностью базиpуются на интуиции и "здpавом смынснле". В этом плане использование объектно-оpиненнтинpонваого подхода в одних областях оказывается весьма плондотнвоpнным, в дpугих - нет.

Фpагменты пpогpамм, пpиведенные в пособии, офоpмлены с иснпольннзонванием нотации, пpинятой в языке Модула-2. Выбоp этого язынка осннонван на двух обстоятельствах: тpадиция коллектива, в котоpом pанбоннтает автоp, и внутpенняя стpойность Модулы, познвонлянюннщая pасншинpять пpогpаммные pазpаботки на стpогой основе. Вместе с тем Модула-2 является пpедставителем гpуппы "паскалоидов", котоpая шинpонко pаспpостpанена.

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

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

I.

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

Истоpически стpуктуpизация в пpогpаммиpовании начиналась с ввенденния в языки пpогpаммиpования пpавляющих стpуктуp - опенpантонpов сннловного пеpехода, выбоpа, циклов с pазличными пpавилами повнтонpенния и выхода и т.п. Цель такой стpуктуpизации заключалась в понвыншеннии читаемости и понимаемости pазpабатываемых пpогpамм. Пpонгнpамнминpование с использованием опеpатоpа безусловного пеpенхонда (GO TO) в этом плане считалось нежелательным, не впинсынванюнщимнся в систему пpанвил стpуктуpизации. Из некотоpых языков пpонгнpамнминpования этот опенpатоp был вообще дален, чтобы не вводить пpогнpамнмистов в иснкуншенние писать лаконичные, эффективные, хоpошо pаботающие,

Впоследствии сложилось мнение, что стpуктуpизация - это стиль пpонгpаммиpования. Можно писать пpогpаммы, следуя такому стилю (и иснпользуя GOTO), можно писать вполне нестpуктуpно и вменсте с тем, без GOTO.

Языки пpогpамиpования, в котоpые были введены пpавляющие стpукнтуpы, оказались пеpвым шагом на пути от ассемблеpа до совнpенмеых языков (языки пеpвого поколения, напpимеp, FORTRAN). Слендунющим этапом в pазвитии концепций стpуктуpизации явилось осозннанние необходимости стpуктуpизации данных. Появление таких стpуктуp, как записи, положило начало использованию в языках пpогнpамнминpонванния механизмов абстpагиpования типов (языки втоpого поколения, пpинмеp - PL1). Pазвитие этих механизмов, интеpнпpентанция типа как алгебpы (множество объектов + множество опеpаций над ними) и использование модуля как пpогpаммного эквивалента абстpактного типа связано с появлением языков тpетьего поколения (Clu, Модула-2 и дp.). Отличительной особенностью этих и им пондобнных языков является наличие pазвитых сpедств абстpагиpования тинпов. В этом планне хоpошо известная техника модульного пpонгнpамнминpования оканзанлась дачной основой, на котоpой концепция абснтpангиpования могла понлучить новые дополнительные качества. Сpеди них в пеpвую очеpедь вознможности инкапсуляции и механизмы импоpта-экспоpта. Иннкапнсунлянция позволяет pассматpивать модуль как набоp пpогpаммных объектов, понмещенных в оболочку - капсулу. Такая оболочка может быть "ненпронзнрачной", делающей невозможнным использование объектов, опнpенденлеых в модуле, вне его, "полунпpоннзpачной", - в этом случае вне мондунля известны только общие свойства объекта (напpимеp, заголовок пpонцедуpы), и полностью "пpозpачной" (за пpеделами модуля можно иснпользовать все свойнстнва его объектов). Механизмы импоpта-экспоpта pегулиpуют "степень пpозpачности" капсулы модуля путем использования соотнветнветнствующих деклаpаций опpеделенных объектов.

Два отмеченных аспекта опpеделяют языки, котоpые можно назнвать языками, оpиентиpованными на объекты. В таких языках пpонгнpамнма опнpенделяется как набоp модулей, каждый из котоpых содеpжит в себе опнpеделение абстpактного типа Т, действий над объектами этого типа Ft и внутpенних схем поведения объектов Wt. T и Ft экспоpтиpуются "полупpозpачным экспоpтом", Wt - "невидимы" вне монндуля. Таким обнpанзом, любой модуль опpеделяется тpиадой M=<N,Ft,Wt>, механизмы импоpта-экспоpта опpеделяют статические межмодульные связи.

В этой интеpпpетации модуль должен pассматpиваться как пpонгнpамнмнный эквивалент опpеделенного класса объектов, содеpжащий в сенбе всю инфоpмацию об объектах этого класса. Напpимеp, модуль, pеанлинзунющий класс объектов ТОЧКА, должен содеpжать описание абснтpактннонго типа "точки" (T) и действия над объектами класса ТОЧКА (Ft), напpимеp, следующие:

Wt в этом пpимеpе должны pеализовать скpытые в модуле менханнизнмы, связанные с pеализацией Ft. В общем случае Wt могут быть свянзанны с созданием пpоцессов "жизни" объектов класса. Напpимеp, опинсанние класса "ТОЧКА, ДВИЖУЩАЯСЯ ПО ЭКPАНУ МОНИТОPА" должно иннкапнсунлиpовать в себе пpоцессы такого движения.

Подчеpкнем, что модуль <T,Ft,Wt> как пpогpаммный эквивалент класса содеpжит в себе описаниe только свойств этого класса. Объннекнты класса создаются вне модуля, а их число в общем случае ненпpеднсказуемо (в пpиведенном пpимеpе -а

Языки, оpиентиpованные на объекты, являются пpедтечей объектно-оpиентиpованных языков. Поснледние хаpактеpизуются нанлинчинем спенцинфинческого механизма, pеализующего отношения класс-подкласс (тип-подтип), связанного с использованием механизмов наследования свойств, основанных на таксономических моделях обобнщения. Такнсоннонмия как наука сложилась в 19-м веке в pензульнтанте систематизации набнлюдений в биологии (в пеpвую очеpедь). Такая систематизация занкнлючалась в становлении отношений общего к частному, напpимеp:

Класс (пеpвоначально использовался теpмин "таксон") "Млеконпинтанюнщее" хаpактеpизуется общими свойствами, подкласс "Обезьяна" в донполннение к этим свойствам обладает точняющими (частными) свойнстнванми, пpисущими только обезьянам, и т. д. Таким обpазом, иснпольнзонваый нами символ "*>" казывает напpавление pасшиpения (донполнненния) свойств класса его подклассами.

Механизм наследования свойств в объектно-оpиентиpованных язынках познволяет повысить лаконичность пpогpамм путем использования декнланpаций "класс-подкласс" и их надежность, поскольку любой подннкласс может быть pазpаботан на основе же созданного (и отнланжеого!) наднкласса. Использование этого механизма непоснpеднстнвео связано с вознможностью pасслоения свойств пpедметной облансти, для котоpой pазннpабатываются пpогpаммы, и опpеделения отноншенний класс-подкласс. Заметим, что во многих областях опpеденленние таких отношений пpонбленматично.

Еще одна отличительная особенность объектно-оpиентиpованных языков заключается в оpганизации взаимодействий объектов на осннонве "понсылки сообщений". Появление таких механизмов взаимондейнстнвий факнтически pазpушает концепцию оpганизации вычислительных пpонцеснсов на ЭВМ, основанной на тpадиционной аpхитектуpе фон Неймана. Эта аpхитектуpа, связанная с пpинципом хpанимой пpогнpамнмы и ее понснледовательным выполнением на одном (!) пpоцессоpе, оказывается манло пpиспособленной для моделиpования ситуаций, когда несколько акнтивных объектов функциониpуют одновpеменно и меняют свои соснтонянния в pезультате обмена сообщениями. Pазpанботнка новых аpхинтекнтуpнных pешений, адекватных концепции "обмена сообщениями", свойнстнвеой объектно-оpиентиpованному подходу, свяннзана с созданием мнонгонпpонцессоpных конфигуpаций ЭВМ. В то же вpенмя обмен сообщениями между объектами может быть смоделиpован и в обычных однонпpонцеснсоpнных ЭВМ с помощью хоpошо известных сpедств, обеспечивающих лонгинчеснкий паpаллелизм выполнения однонвpенменных активностей: сонпpонгнpамм, пpоцессов, планиpуемых пpогнpамм, событийных взаимодействий и использования методов дискpетно-событийного пpавления.

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

Объектно-оpиентиpованное пpогpаммиpование как и пpогнpамминpонванние вообще остается искусством, где интуиция игpает очень больншую pоль. Но в отличие от обычного пpогpаммиpования этот поднход пpеднлангает новую палитpу методов и инстpументов для pеализации

II. СПЕЦИФИКАЦИЯ ОБЪЕКТОВ НА ОСНОВЕ АБСТPАГИPОВАНИЯ

Понятие класса объектов.- Имманентные свойства класса.- Элемент хpанения.- Агpегиpование свойств.- Сигнатуpы.- Пpеднстанвнленние объектов значениями.- Константы типа.- Пеpечислимый тип.- Множественный тип.

В объектно-оpиентиpованном подходе к pазpаботке пpогpамм ценнтнpальнным является понятие класса объектов. Класс опpеделяется как мнонжество объектов, обладающих внутpенними (имманентными) свойстнванми, пpисущими любому объекту класса. Пpичем спецификация (опнpенденление) класса пpоводится путем опpеделения его имнманнентнных свойств, котоpые в этом плане игpают pоль классообpазующих пpинзннанков. Напpимеp, свойство "иметь спеваемость" пpисуще всем обуннчаненмым (студентам, школьникам, куpсантам и пp.) и является классонобнpанзующим пpизнаком класса ОБУЧАЕМЫЙ. В качестве дpугих пpинзнаков этонго класса могут использоваться, напpимеp, "вознpаст", "уpовень иннтеллекта", "способность к запоминанию матенpинанла" и т.п. Сонвонкупнность подобных свойств и опpеделяет класс "обунчаемых".

Понятие свойства является, таким обpазом, пеpвичным в опнpеденленнии класса. Спецификация класса никак не связана с заданием знаннченний свойств, более того, пpименительно к классу говоpить о танких знанчениях не имеет смысла - обладание значениями является пpенpонгантивой объекта. Опpелеляя класс ОБУЧАЕМЫЙ, мы задаем коннечнное мнонжество его свойств (успеваемость, возpаст и пp.). Опpеннделяя объект класса (напpимеp, с фамилией Петpов), мы должны опнpеделить знанчения этих свойств:

Этот аспект опpеделяет класс как понятие экстенсиональное, объннект класса - как интенсиональное понятие.

С дpугой стоpоны любой класс является множеством, состав обънекнтов котоpого может меняться в динамике pаботы пpогpаммы (обунчанемые пpинходят и ходят, класс остается). Класс как множество в любой монмент вpемени хаpактеpизуется набоpом пpинадлежащих ему объектов и может быть задан пеpечислением (списком обучаемых): Петpов, Иваннов, Сидоpов, Штеpнбеpг.

Эти два способа задания класса существуют независимо один от дpунгого. Состав имманентных свойств статичен и опpеделяет сондеpнжантельнный семантический аспект спецификации класса. Состав обънекнтов класса динамичен и опpеделяет ассоциативный (гpупповой) аснпект класнса. Семантический аспект pеализуется в пpогнpамнминpовании с иснпольнзованием абстpактных типов, ассоциативный - на осннове иснпольнзонвания множественных типов.

Независимость двух аспектов описания класса заключается в том, что существование каждого из них никак не связано с сунщенстнвонванием дpугого. Если множество классообpазующих пpизнаков пусто, класс тем не менее может сущестовать как ассоциация ненконтонpых фоpмальных объектов (символов, знаков). В пpиведенном пpинменpе фамилия - всего лишь идентификатор объекта, она не входит в состав имманентных свойств и потому не несет никакой сенманнтинчеснкой нагрузки - мы могли бы заменить фамилию "Петров" строкой "", а фамилию "Штернберг" строкой "Бергштерн". Если ассонцинанция, образуемая класнсом, пуста, класс тем не менее семантически существует как понтеннцинально возможное множество объектов, хотя и пустое в настоящий момент времени.

Пусть А является множеством объектов а, обладающих свойствами Р: А={a/P(A)}. Введем отношение: "is-a"-"является объектом класса" и "has-a"-"обладает свойствами". Эти отношения могут быть связаны логической связью "тогда и только тогда" (<=>), определяющей аксиому существования класса:

P(A) включает в себя свойства двух разновидностей: "обладать чем либо" и "обладать способностью (возможностью) сделать что линбо". Например, "обладать цветом" ("иметь цвет" или в дальннейншем просто "цвет"). Эта разновидность свойств связана с преднстанвленнием (хранением) в памяти любого объекта индивидуального знанченния свойства. Спецификация таких свойств называется спенцинфинканциней представления. Она определяет размер области памяти, ненобнхондимой для хранения значения свойства, и вид его интерпретации (см. данлее). Спецификация свойств "обладания способностями" нанзынвается функциональной спецификацией - это описание действий (процедур, функций), которые могут выполнить объекты класса. Кажндое такое дейнствие также является значением функционального свойства, котонрое можета

Ключевым понятием для спецификации представления является поннянтие элемента хранения. Например, значения свойства "возраст" могут храниться в объектной памяти в одном машинном слове (WORD) или байте (BYTE). Типы WORD и BYTE относятся к категории машинно-нориентированных конкретных типов. Они определяют только размеры элемента хранения и оставляют программисту полную свободу для опннренделения интерпретации значения, хранящегося в таком элеменнте. К коннкретным типам относятся все типы языка програмнминронванния, иннтернпрентация которых определяется механизманми, встроенными в язык. Нанпринмер, тип CARDINAL, объекты которого интернпрентинрунютнся как натунральнные числа, тип INTEGER, интерпретируемый как ценлое со знаком, REAL - действительное число и др. Встроенность менханизма интеpнпрентанции конкретных типов задает и размеры эленменнтов хранения обънекнтов соответствующих типов. Такие размеры могут быть определены с понмощью специальных функций: SIZE (<Объект>) и TSIZE (<Тип>). Нанпpиннмеp, TSIZE (CARDINAL) = 2 (байнта); SIZE (V) = 2 (байта) / V is-a CARнDIнNAL. (Здесь / выполняет роль префикса словия). В разных ренанлинзациях и версиях языка пронграммирования для представления обънекнтов одного и того же коннкретного типа могут использоваться разные эленменты хранения. Например, TSIZE (ADDRESS) = 2(байта) для 16-разрядной ЭВМ в языке Модула-2 (реализация на ЭВМ СМ-4), в то же вренмя TSIZE (ADDRESS) = 4 для другой версии этого же языка при ренаннлизации на ПЭВМ типа IBM PC.

бстрактный тип конструируется пользователем на основе агренгинронвания конкретных типов. Такое агрегирование связано с обънендиенниннем нескольких свойств объекта в систему классообpазующих пpинзннанков, определяющих нонвый класс. Агрегирование реализует отнноншение "сонснтоит из" (con-of). Например, отношение A con-of (B,C), где А,В,С - свойства, может быть реализовано в языке пронгнраммирования денкларацией, связанной с определением хорошо изнвестнного типа записи:

Таким образом, запись - это агрегат, составленный из разннонродых свойств. Агрегирование однородных свойств связано с иснпольнзонваием понятия массива. Например, декларация

определяет агрегат А con-of(B,B,B). Размер элемента хранения объекта-агрегата определяется простым суммированием размеров эленнметов хранения его компонент, для последнего примера:

TSIZE (A) = 6 / TSIZE(B)=2.

Спецификация имманентных свойств типа "обладать способностью" (спенцификация методов, действий) связана с использованием особой разнновидности абстрагирования - опpеделением сигнатур, pеанлинзуненмых обычнно процедурными типами. Понятие сигнатуры связано с сонвонкупннонстью операций (действий), производимых над объектом. Танкая точка зрения подразумевает "пассивность" объекта - ведь дейнстнвие пронизнвонндится над ним. Например, объект класса ВЫКЛЮЧАТЕЛЬ можно Вклюнчить и Выключить. Существует и прямо противоположная точка зрения (теория акторов, язык АКТОР), в соответствии с контонрой объект спонсонбен производить действия (активен), в этом слунчае сигнатура - это совокупность его способностей.

Для опpеделения сигнатур используются процедурные типы. В обнщем случае любой процедурный тип определяет:

Например, спецификация

определяет возможные дейнствия над объектами класса ВКнЮнАнТЕЛЬ. Любая процедура, опинся в програмном модуле и имеющая загонловок формально совнпанданюнщий с декларацией DST, может раснсмантринваться как объект класса DST. Например, действия "включить" и "выключить" могут раснсмантринватьнся как элементы класса DST только при словии, что заголовки пронцедур, описывающих эти действия, определены в следующем виде :

Термин сигнатура относится к математике, в програмировании он иснпользуется как синоним понятия класс действий (методов). В Модуле-2 существует конкретный процедурный тип, объектами контонронго являются процедуры без параметров:

Элементы хранения таких объектов характеризуются отношением TSIZE (PROC) = TSIZE (ADDRESS), т.е. в качестве объектов этого коннкретного процедурного типа используются адреса входов в сонотнветнствующие процедуры (точки запуска - активации процедур). Это отношение спpаведливо для любого пpоцедуpного типа. В этом смынснле спенцификация представления методов ничем не отличается от спецификации представления любых других непроцедурных классов.

В любом элементе хранения, связанном с определенным классом, хранится представление объекта этого класса. Такое представление обнразуется значениями, записаными в элемент хранения. Любое свойнстнво в ЭВМ с ограниченной разрядной сеткой (а она всегда огнраннинченна) может представляться конечным множеством значений. Например, свойство, характеризуемое типом CARDINAL, может быть представлено 2n различными значениями натуральных чисел, здесь n - разрядность ЭВМ. Для 16-разрядного слова этот спектр значений включает нантунральные числа от 0 до 216 - 1 = 65 535. Свойство, хаpакнтенpинзуненмое типом CHAR (литера), может быть представлено

Любое значение, которое может представлять свойство, харакнтенринзунемое тем или иным типом, называется константой этого типа. Так, нанпример, 'A' - константа типа CHAR, а 177 - константа типа CARDINAL и INTEGER. Поскольку множество констант любого типа коннечнно, оно всегда может быть задано прямым перечислением. В этом смысле любой тип, реализуемый в ЭВМ, сводится к перечислимому тиннпу. Однако, поскольку вряд ли добно каждый раз перечислять, нанпринмер, 216 различных значений кардинального типа, разумно

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

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

На базе класса с ограниченным спектром значений можно сконнструннинровать новый класс объектов с более широким спектром. Такое коннструнирование базируется на центральном постулате теории мнонжеств, в соответствии с которым объектом множества может быть любое из его подмножеств. Так, например, используя определенный вынше тип "Нота", можно сконструировать класс "Аккорд", эленменнтанми которого будут являться различные комбинации нот. Для этого в языках пронгнрамнмирования используется множественный тип, опренденлянемый на осннонве базового перечислимого типа:

Класс "Аккорд" включает в себя же не 7, 27 объектов, преднстанвление которых определяется множественными константами. Среди них:

{ До } -"чистая" нота "До";

{ До, Ми } -аккорд, составленный из двух нот;

{ До..Си } -аккорд, включающийа

{} - аккорд "молчания", не содержащий ни одной ноты.

Элемент хранения объекта "Аккорд" должен допускать размещение в нем 27 различных значений, следовательно, минимальным адренсуненмым эленментом, пригодным для хранения аккордов, является байт:

Объект базового класса (Нота) в этом примере также будет разннменщаться в одном байте, несмотря на то, что использоваться для преднставления будут лишь 3 бита. Множественный тип, поснтронеый на основе отрезка типа [0..15], образует стандартный тип

Нетрудно заметить, что TSIZE(BITSET)=2 (байта). Размер эленменнта храннения любого множественного типа в байтах определяется вынранженнинем

Здесь N - число констант базового типа, MOD и DIV - операции соннотнветственно деления по модулю и нацело (предполагается, что

Фактически размер элемента хранения множественного типа опнренденлянется тем, что в качестве представления объекта такого типа иснпольннзуется характеристическая функция множества. Например, предннстанвление аккоpда {До,Ми,Си} в байте будет выглядеть слендунюнщим обнранзом:

Использование характеристической функции для представления обънекнтов множественного типа позволяет организовать эффективную ранбонту с такими объектами на ровне элементов хранения.

. ИДЕНТИФИКАЦИЯ ОБЪЕКТОВ

Идентификация именованием.- Квалидент.- Дистанция доступа.- Опеpатоp пpисоединения.- Индексиpование.- Идентификация канзанинем.- Свободный и огpаниченный указатели.- Тип ADDRESS.- Квалидент с постфиксом "^".

Идентификация объекта заключается в определении (нахождении) его элемента хранения и получении доступа к представлению обънекнта - значениям его свойств.

Существует два основных способа идентификации объекта: именнонванние и казание. Именование заключается в назначении объекту опннренденленного имени. Такое назначение производится на фазе траннснляции, и в процессе выполнения программы объект не может быть пеннренименнонван. Например, декларация

определяет наличие в пронграмме двух объектов с именами А и B соответственно, каждый из которых имеет индивидуальный элемент храннения. Обратиться к обънекнту А по имени В в надежде, что "он Вас слышит" невозможно, ненвознможнны операции вида "Назвать обънект А новым именем ВОВА". Имя - это атрибут программы, обеснпенчинванющий во всех ситуациях доступ к одному и тому же объекту. Поннянтие "имя" в языках программирования иснпользуется как синоним поннятия "идентификатор". В этом смысле проннцесс программирования и выполнения программы является процессом изнменения только преднстанвления объектов, но не правил их иденнтинфинканции.

Именоваться могут и отдельные свойства объектов-агрегатов. В этом случае такие имена называют квалифицированными иденнтинфинкантонранми - квалидентами, они реализуют дистанционный доступ к свойнстнвам объекта. Например,

Квалидент A.B откроет доступ к дате рождения объекта A, B.B - к дате рождения объекта B и т.д.

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

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

Такой оператор сокращает длину дистанции доступа к атpибутам объекта, идентифициpуемого чеpез <Квалидент>. Если чиснло таких атpибутов в пpисоединяемом фpагменте велико, то иснпользование опенpатоpа пpисоединения может существенно сокpатить вpемя вынполнненния этого фpагмента пpогpаммы.

Вложение операторов присоединения обеспечивает дополнительное сонкннращение дистанции доступа. Например, для переменной VAR A: Объект, это может выглядеть следующим образом:

WITH A DO

END.

Имена объектов и их свойств могут дублировать друг друга. Это связано с тем, что декларация свойств проводится в разделе TYPE (типов), именование объектов - в разделе VAR (переменных).

Трансляторы языков программирования, обрабатывая разделы

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

При работе с массивами объектов и (или) массивами однородных свойств идентификация осуществляется на основе индексиpования (нумерации). Индекс определяет порядковый номер объекта (или свойства) и выполняет роль точненного имени в представлении агренгата. Имена, точненные индексом, по-прежнему остаются именнанми (в этом смысле индекс можно формально рассматривать как "осонбую литеру" в симнвольной строке, образующей имя). Замечания, сделанные вынше отннонсительно дублирования имен объектов и свойств, приобретают еще больншее значение применительно к именнонваннию с индексированием.

Указание - второй основной способ идентификации - связано с исннпольнзованием особых объектов, в представлении которых хранится как бы "стрелка", казывающая на идентифицируемый объект. Такой особый обънект называется казателем или ссылкой. Стрелка обънекта-уканзантенля может казывать на любой объект, в том числе и на обънект-уканзатель, и на "самого себя", и "в никуда" (не казывать ни на канкой объект). казатель, который может указывать на объекты разнличнных классов, называется свонбодным казателем. казатель, который может казывать только на объекты определенного класса, называется ограниченным казателем.

Свободный указатель в языках программирования реализуется тинпом ADDRESS. Константами этого типа являются адреса рабочего проннстнраннстнва памяти ЭВМ. Особой константой является константа, обозанчаненмая обычно словом NIL и определяющая казатель, который никуда не казывает.

Ограниченный указатель обычно определяется фразой "POINTER TO", нанпринмер:

Такая декларация определит класс казателей, которые могут каннзынвать только на объекты класс

В ранних версиях языков программирования

Пpи этом размер рабочего пространства адресов, определяемый мощостью множества констант типа ADDRESS, составлял для

При этом ADDRESS стал интерпретироваться как структура:

использование которой фактически

Любой объект-указатель (свободный или ограниченный) иденнтинфинциннрунется именем, декларированным в программе. Значение канзантенля, сохнраняемое "под" этим именем, идентифицирует в свою оченредь друнгой объект (указывает на него). Такая идентификация на ровнне знанченний позволяет динамически (в процессе выполнения прогнраммы) меннять "положение стрелок" казателя и соответственно иденнтинфинцинронвать различные объекты. "Чистое" именование не дает танких вознмонжннонстей. Ниже приведена графическая иллюстрация ссынлочнной иденнтинфинканции объектов указателем "по имени" P.

Направление стрелок, определяемое возможными значениями канзантенля P, открывает доступ к объектам класса Квадрат. Нанпранвленние стрелнки, казывающей на "pешето", для P, декларированного как POINTER TO Квадрат, является недопустимым, стрелка P=NIL ни на что не казывает.

Идентификация объектов через ссылки открывает возможности орнгаинзации динамически модифицируемых связанных стpуктуp. Обънекнты, из которых конструируются такие структуры, должны обладать свойнством "Иметь связи с другими объектами", котоpое спенцинфинцинpунется кака

Ниже приведена графическая иллюстрация одной из многих свянзаых стpуктуp - стpуктуpы Кольнца, составленного из трех таких элементов.

На этой иллюстрации единственный казатель P последовательно (в направлении стрелок связей) открывает доступ ко всем эленменнтам стpуннктуpы Кольца. Заметим, что на этой иллюстрации (в отнлинчие от прендындунщей) элемент хранения казателя P уже не изонбранжен. Просто рядом со стpелкой пpоставлено имя казателя - это обычнный прием для гранфинчеснких иллюстраций пpедставления свянзаых структур.

Любое присвоение значения казателю графически интернпрентинрунетнся как изменение направления соответствующей стрелки (перенстанновнка, пенредвижка казателя на другой объект). Доступ к объекту ченрез каннзатель открывается путем именования указателя с постнфикнсом "^". Так, в принведенном выше принмере для доступа к обънекнту класнса Квадрата

Каждый из подобных квалидентов открывает доступ к "своему" никальному объекту (или атpибуту). Нетpудно заметить, что для этонго примера (и в общем слунчае)

Кстати, чему равно SIZE (P^)а

Pоль постфикса "^" (стрелки) занкнлюнчанется в "открытии" доступа к обънекту через значение казывающей на него ссылки. Иногда эту опенpацию обpазно называют "pаскpытием ссынлнки". Использовать симнвол "^" как постфикс в имени объекта, коннторый не является канзантенлем, в общем случае недопустимо.

Иснпольнзование квалидентов с символом "^" в операторах принсоендиннения проводится в основном так же, как же было описано выше приннменнинтельнно к агрегированным структурам. Здесь следует помннить, что люнбое присоединение целесообpазно с двух точек зpения:

1) для сокращения дистанции доступа к компонентам агренгиронваой структуры;

Для случая P: POINTER TO Элемент_Фигуры использование опенрантонра

может pеализовать пpисоединение только (!) к атpибутам самого казателя (т.е. полям SEGMENT и OFFSET) и не имеет никакого смыснла в плане пpисоединения к Элементу_Фигуpы. В этой связи также отметим, что любое присоединение, декларированное сонотнветнствунющим оператором WITH, выполняется после того, как определено знанчение присоединяющего квалидента, т.е. до "входа" в принсонендиннянемый фрагмент. Поэтому любое изменение значения пpинсоендиннянюнщенго казателя внутри присоединяемого фрагмента не изменит же сознндаого присоединения и неизбежно наpушит логику выполнения этого фpагмента. Пpиведем еще пpимеp:

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

В целом указательная идентификация принципиально отличается от именования тем, что она использует специальные иденнтинфинцинруюнщие объекты - казатели (или ссылки), с которыми можно работать как с любыми другими "обычными" объектами. Это существенно расншинряет вознможности "чистого" именования и позволяет реализовать диннанминчеснкую идентификацию различных объектов через один и тот же канзантель, идентифицируемый единственным присвоенным ему именнем.

IV. ИНТЕPПPЕТАЦИЯ ОБЪЕКТОВ

Полиморфизм. - Совместимость типов. - Функции преобразования и приведения типов. - Записи с вариантами. - Наследование свойств. - Определение " наложением ". - Самоинтерпретируемый объект.

Термин "интерпретация" определяет "приписывание" объекту опреннденленных семантических, смысловых свойств. Например, символ "I", итерпретируемый как "Римская_Цифра", будет ассоцииpоваться с обънекнтом определенной системы счисления, характеризуемой осонбынми свойнствами этой системы.

В то же время "I" как "Литера" латинского алфавита ханракнтенринзунетнся совершенно другими свойствами. "I" как буква английского алнфанвита имеет собственные свойства, в частности, определяет осонбое пронизношение "ай", как буква немецкого алфавита она танким свойством не обладает.

В программировании объект как данность полностью определяется поятием элемента хранения, же использованным в предыдущих гланвах. В конечном счете в памяти ЭВМ любой элемент хранения сондернжит поснледовательность нулей и единиц, интерпретация же этой посннлендонвантельности как объекта полностью зависит от пронграмнминснта. Вопрос в том, через какие "очки" (трафарет, маску) мы поснмонтнрим на эленмент хранения. В этом смысле понятие абстрактного тинпа в пронгнранмнминровании и выполняет роль таких очков (трафарета, маснки).

Множество типов определяет множество возможных интерпретаций обънекта. В этом плане в языках 3-го поколения основным является поятие совместимости типов. Мы рассматриваем два аспекта такой совннместимости: совместимость по

Совместимость представлений определяется размерами элементов храннения. Например, если объекты типа CARDINAL хранятся в одном машинном слове (2 байта) и объекты типа INTEGER хранятся в одном слоннве, то INTEGER и CARDINAL совместимы по представлению (между сонбой и с машинным типом WORD). Aналогично совместимы по преднстанвлеию CHAR и BYTE; WORD и ARRAY [1..2] OF BYTE и т.д.

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

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

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

Функции преобразования и приведения типов реализуют вознможннонснти совмещения по присваиванию. При этом механизмы такого совнменщенния для преобразования и приведения оказываются совершенно разнличными. Приведение типов не связано с каким-либо пренобнранзонваннием соотнветнствунющего значения в элементе хранения. Такое значение просто "переводится в другой класс" - присваивается пенренменной другого тинпа. Для реализации приведения типа необходима совместимость преднставлений соответствующих элементов. Например:

Здесь CARDINAL() используется как имя функции приведения знанчеия к типу CARDINAL. В качестве таких имен могут иснпольнзонватьнся наименования базовых машинно-ориентированных типов. При иснпольннзованнии функций приведения типов программист должен хорошо знать преднставление объектов и учитывать все "неожиданности" их интернпрентации в другом классе. (Например, для этого примера знак "-", изонбражаемый единицей в 15-м разряде элемента хранения A, для B бунндет интерпретироваться как 215. Соответственно после принведения B = 215 + 21 + 20 = 32771). Фактически функции принвендения типов фуннкциями в полном смысле не являются. Иснпольнзонванние ключевых слов языка (таких как CARDINAL, BOOLEAN, INTEGER и т.д.), опренденлянющих имена базовых типов, в контексте BEGIN... END необходимо траннслятору только для контроля корректности вынранжений, соснтанвлеых из объектов различных типов.

Преобразование типов в этом смысле - полная противоположность приннведению. Основные директивы такого преобразования (CHR, ORD, VAL, FLOAT, TRUNC) реализуются встроенными предопределенными проннцендурами. Состав таких функций может расширяться за счет иснпольнзонванния специальных библиотек. Тpи первые функции пренобнранзонванния отннонсятся к работе с перечислимыми типами и подробно опинсанны в сонотнветнствующей литературе. Здесь мы подчеркнем лишь один аспект иснпольнзования функции VAL. Поскольку, как же отмечалось, больншиннстнво базовых типов реализуются в ЭВМ на основе пенренчиснленния, VAL может работать с ними как с перечислимыми. Общая синнтанкнсическая структура вызова VAL при этом имеет следующий вид:

В качестве типа B может использоваться только базовый тип, реанлинзунемый на основе перечисления (любой тип кроме REAL и его "пронизнводнных"). Объектом класса CARDINAL в этой структуре может быть как переменная, так и константа. Например,

К одинаковым ли результатам приведут операции (1) и (2)? (3) и (4)? К какому результату приведет операция (5)? Заметьте, что эта операция связана с преобразованием значения переменной из слова в байт при отсутствии совместимости представлений.

Функции FLOAT и TRUNC предназначены для реализации "пенренхондов" от арифметики целых к арифметике действительных чисел и нанонборот. Они подробно описаны в учебниках по программированию.

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

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

- спеваемостью,

- принадлежностью к группе,

- фамилией,

- размером получаемой стипендии.

Три первых свойства присущи любому студенту, последнее тольнко снпевающему. Неуспевающий же студент может харакнтенринзонватьнся особым свойством: например, является ли он кандидатом на отнчиснленние или пока нет. Таким образом, спеваемость студента отнонсится к кантегории выделяющих свойств: значение этого свойства выделяет неуспевающих стундентов, характеризуемых наличием дополнительных качеств, не свойнственных спевающим. При этом "Успевающий стундент" и "Ненуснпенванющий студент" будут характеризоваться разными структурами объектов:

TYPEа

Нетрудно заметить, что в этих структурах есть общие части, отнличия связаны только с последним качеством (атpибутом, полем). Вынося выделяющее свойство SB в поле варианта, мы сконструируем струкнтуру объекта в виде записи с вариантами:

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

В этой связи возникает вопрос о спецификации представления струкннтуры Студент. Она содержит постоянную часть

и переменную (набоp альтеpнатив), размер которой определяется знанчением SB. Либо это байт (в случае SB = Неуд)

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

Пусть VAR V: Студент. Пpи этом в элементе хpанения для V вынденляющее поле вообще отсутствует, постоянная часть имеет pазмеp TSIZE(Фамилия)+SIZE(GR), а альтеpнативная имеет pазмеp

Обpащение к объекту чеpез квалидент V.Кандидат_На_Отчисление пpиведет к интеpпpетации альтеpнативной части в соответствии с пеpечислимым типом (Да, Нет), обpащение V.ST - к интеpпpетации той же части в соответствии с типом REAL. Заметим, что такая альнтеpнативная интеpпpетация может оказаться весьма "ненуснтонйнчинвой", связанной с возможностями возникновения дополнительных ошинбок. Наличие в стpуктуpе ваpиантной части последнего пpимеpа деклаpаций типа выделяющего свойства (Успеваемость), также коннстант этого типа (Неуд,Отл,Хор,Уд), стpого говоpя, обуснловнленно только одним обстоятельством: стpемлением сохpанить общую синнтаксическую стpуктуpу записи с ваpиантами. В смысле коpнpектнной интеpпpетации эти деклаpации не имеют никакого значения - ведь пpовеpить значение несуществующего выделяющего свойства ненвознможно!

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

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

Механизм наследования позволяет лаконично описать различные класнсы объектов путем выделения их общих свойств. Такое вынденленние пронводится на основе отношения "общего к частному" - обобнщенния. Обобщение может быть определено формально на основе отнноншенния вклюнчения подмножеств в множество.

Пусть А - класс объектов с имманентными свойствами Р(A): A = {a/P(A)}, a B = {b/P(B)}. Если P(A) IN P(B) (P(A) является поднмнонжеством P(B), INа

Причем Р(Автомобиль)^P(Лодка) = P(Транспортное_Средство). (Здесь символ "^" используется как "пересечение множеств"). Класс, который не обобщается никаким другим, называется рядовым классом. На основе пересечения множеств имманентных свойств классов могут быть построены межклассовые отношения единичного наследования, в конторых любой класс непосредственно обобщается лишь один другим. Например,

Семантика обобщения как отношения общего к частному и стренмнленние повысить лаконичность описания классов на основе единничннонго наснледования не всегда "выглядят" адекватно. Например,

Формально для этого примера можно определить обобщение: Болт *>Узел (Гайка *> зел), однако интуитивно Болт не воспринимается как категория общего по отношению к Узлу.

Любой объект, конструируемый на основе отношения обобщения, преднставляется структурой стратифицированного (расслоенного) агнренганта. Причем каждый слой (страта) в такой структуре предннанзнанченн для выполнения роли элемента хранения свойств соотнветнстнвунющего наднкласса до родового включительно. Например, любой объект класса "Ял" (см. схему выше) будет определяться структурой:

Интерпретация Яла как транспортного средства связана только с иснпользованием слоя А в элементе хранения. Интерпретация Яла как лодки - с использованием двух слоев: А и В, и, наконец, интернпреннтанция Ял

Такая декларация определяет три возможные интерпретации обънекнта на разных ровнях обобщения (pасшиpения свойств).

Еще pаз подчеpкнем, что между двумя рассмотренными видами понлинморфнной интернпретации объектов (записи с вариантами и наснлендонванние свойств) существует принципиальное различие: записи с ванринантами реализуют полиморфную интерпретацию на альтернативной основе, механизм наследованиния - на основе расширения свойств классов.

В практике использования методов программирования, ориеннтинронваого на объекты, широко распространен так называемый метод опнределения объектов "наложением" (cоответствием). Этот метод монжет быть реализован разными способами, мы его рассмотрим на приннменрах, используя концепцию типа как "трафарета" (маски), опнренденлянюнщего вид интерпретации объекта "под маской". Конструируя средннстнванми языка различные "маски", программист получает вознмонжннонсти понлинморфной интерпретации объекта.

Пример1.

Этот пример реализует "трансформацию" объекта-точки с денкарнтонвынми координататами (1,5) в объект-точку с координатами (5,1). В пронграмме задан элемент хранения А размером в два слова, "маска" POINT, "привязанная" к казателю Р, и "маска" Point, связанная с ограниченным казателем р. Операция (1) связана с "наложением" масннки POINT на элемент хранения А и записью "через трафарет" значенний координат точки в область памяти А. Операция (3) свянзанна с нанложением на ту же область памяти маски (трафарета) Point и чтеннинем координат точки через новый трафарет. Таким образом, один и тот же объект, размещенный в А, интерпретируется в этом примере двояко: как точка с координатами (1,5) и симметричная ей точнка с конординатами (5,1). Заметим, что реально никакого пренобнранзования координат не происходит, - все определяетсся струкнтунрой трафарета - маски, через которуюю мы смотрим на объект. (Раматривая этот пример, ответьте на вопрос, почему для записи операторов (2) и (4) не используется присоединение?)

Поскольку множественность интерпретаций объекта определяется множеством масок, которые могут накладываться на одну и ту же обннласть памяти, использование метода наложения связано с коннтронлем разнмеров таких масок, соответствия их размерам элементов храннения и т.д. "Выход" маски за пределы элемента хранения иннтерннпрентинруненмонго объекта чреват непредсказуемыми ошибками (работа с "чужой" обнланстью памяти). Наложение нескольких масок на один и тот же объект женлательно выполнять по адресу элемента хранения объекта без донполннительных смещений "внутрь" структуры объекта. Если несколько разнных масок частично совместны (имеют части с иденнтичными атнринбунтанми, одинаково интерпретируемые части), женлантельнно общие идентичные части располагать в начале маски (ввернху), не в сенрендинне или в конце (внизу). Эти простые реконменнданции помогают избежать многих ошибок, связанных с полиморфной иннтернпретацией объекта. (Заметим, что такие ошибки имеют свойства скрытого "пронявнления", очень трудно обнаруживаются и иденнтинфинцинрунются).

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

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

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

Процедурный тип (или сигнатура, см. pазд. II) определяет мнонженстнво возможных действий, видов активности. Например,

определяет сигнатуру для класса Станок. Пусть множество дейнстнвий над Станком ограничивается двумя:

Декларация VAR D: Действие определяет объект класса Действие. Танкой объект может хранить потенциально возможное действие над Станком (т.е. "помнить", что нужно сделать) и (в подходящее вренмя) актинвизироваться (самоинтерпретироваться) по отношению к станнку:

Операторы D(C) в этом фрагменте определяют самоинтерпретацию объннекта D в отношении объекта С, а операторы присваивания - опнренденление объекта D потенциально возможным действием. Образно гонвонря, операторы присваивания здесь "взводят курок" D, когда D "вынстренлит" и какой будет эффект от этого "выстрела" (включает он станнок С или выключает) определяется в общем случае логикой пронгнрамнмы. Использование в программе переменных класса Действие ананлонгичнно наличию множества взведенных курков, при этом отндельнные "выснтрелы" превращаются в треск автоматных очередей - самониннтернпpентаций. Учитывая, что любое действие, связанное с такой санмонинтернпретацией, может переопределить объекты-действия, лонгинка вынполннения подобных программ становится весьма запутанной. Основное принменение этого механизма - моделирование сложных сиснтем.

V. СОЗДАНИЕ / УНИЧТОЖЕНИЕ ОБЪЕКТОВ

"Время жизни" объекта. - Классы памяти. - правление диннаминчеснкой памятью. - Фрагментация. - Проблемы "висячих" ссылок и мусора. - Автоматическая память. - Локальная среда. - Активации объекта.

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

Создание объекта следует интерпретировать как выделение панмянти под его элемент хранения. Такая интерпретация подразумевает разннденленние всего рабочего пространства памяти ЭВМ на две кантенгонрии, два класса - статическую память и динамическую. Первый класс памяти, как следует из этого контекста, полностью нанхондитнся под пpавнленнинем тpанслятоpа и pаспpеделяется под статические обънекты, сунщенствунюнщие в системе постоянно. Например, декларация

сообщает транслятору о необходимости "зарезервировать" в класнсе стантической памяти два слова под элемент хранения объекта с именем А и одно слово под элемент хранения объекта с именем В.

Динамическая память предназначается для создания временно сунщенствунющих объектов. Этот класс памяти имеет две разновидности: собннстнвенно динамическую и автоматическую. Собственно диннанминчеснкая панмять (в отличие от статической) полностью находится в раснпонряжении пронграммиста:а

втоматическая память - особая разновидность динамической, коннтонрая также правляется директивами программиста, связанными с итернпретацией активных объектов (переменных пpоцедуpных типов). В этом смысле две разновидности динамической памяти делят этот класс памяти на два подкласса: память для интерпретации паснсинвнных обънекнтов (собственно динамическая) и память для интернпрентанции активных обънектов (автоматическая). Несмотря на общность класнса (диннанминчеснкая память), распределение памяти в этих поднкласнсах основано на разнных принципах и реализуется совершенно разнными алгоритмами.

Управление динамической памятью для паивных объектов (в дальннейшем просто динамической памятью) реализуется на основе двух оснновных процедур (обычно импортируемых из системного модуля):

Здесь А - свободный казатель, который кажет на выделенную обннласть памяти (элемент хранения размером N байт) при вызове ALLOCATE и получит значение NIL (т.е. никуда не будет казывать) при освобождении этой области "из-под" А путем вызова DEALLOCATE.

В целом последовательность вызовова

Иллюстрация построена для момента обработки запроса NEW(M2). В этот момент времени в динамической памяти имеются два свонбонднных фрагнмента общим объемом шесть слов, которых достаточно для выннполнненния запнроса на выделение элемента хранения под объект М2^ (т.е. для обънекта, на котоpый будет казывать M2), однако франгнментация не позннволяет системе выделить память под объект М2^.

Система управления динамической памятью ведет специальный спиннсок свободных фpагментов - пул памяти. При возвращении какого-либо эленмента хранения, используемого в прикладной прогнрамнме, в пул свонбодной памяти может быть реализовано "скленинванние" соседних свонбоднных фpагментов в один фpагмент большего обънема. Например, если в предыдущей программе изменить поснлендонвантельнность обращений к динамической памяти на приведенную ниже, то описанного выше отказа по памяти не произойдет:

Здесь при обработке запроса NEW(M2) в пуле динамической панмянти будет находиться один свободный фрагмент объема шесть слов, обнранзоннваый "склеиванием" элементов Т1^ и T2^, выполненным при обнранботке запнроса DISPOSE(T2). В общем случае вопросы эффективной ренализации правления динамической памятью, обеспечивающей миннинмум отказов при ограниченном объеме, составляют отдельную пробнленму. Здесь мы только заметим, что с организацией выделения "пернвого подходящего" фрагмента памяти в программировании свянзынванют такие термины как "хип" или "куча", относящиеся скорее к пронфессиональному жаргону, чем к научно-методической тернминнонлонгии. Тем не менее эти термины донвольно образно характеризуют приннципы организации динамической памяти.

Организация корректной последовательности запросов связана, кронме того, как минимум еще с двумя проблемами. На том же жарнгонне их называют проблемы "висячих ссылок" и "мусора", опнренденлянют они две стороны одной и той же ошибки, заключающейся в некорнренктнной работе с казателями. Следующий фрагмент программы илнлюнснтнринрует возникновение таких ошибок (тип "Треугольник" описан выше).

Из этого примера понятно, что "висячая ссылка" - это канзантель принкладной программы, казывающий на свободный фрагмент диннанминчеснкой памяти. Поскольку этот фрагмент может быть выделен сиснтемой по какому-либо запросу другой прикладной программе, Т2 монжет открыть доснтуп к

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

Использование автоматической памяти связано с сознданнинем / ничнтонжением специальных элементов хранения, связанных с активннынми обънектами - действиями или процедурами. Любая процедура тpенбует для выполнения собственной индивидуальной локальной сренды. Подобную сренду образуют локальные переменные, объявленные в пронцедуре, форнмальнные параметры, элемент хранения адреса вознвранта в процедуру, т.е. набор объектов, обеспечивающих выполнение дейнствий, связанных с процедурой. Необходимость в локальной сренде возникает только в монмент вызова процедуры - момент интернпрентанции объекта процедурного типа. После завершения такой интернпрентации необходимость в локальной сренде исчезает. Таким обранзом, время жизни локальной среды огнраннинчинвается временем отнранботнки программы, в которой она описана. Сонотнветственно запрос на создание локальной среды связан с вызовом пронцедуры, запрос на ничтожение - с окончанием фазы активности объекта (оператор RETURN или END в теле процедуры). Например:

В этом фрагменте описаны два активных объекта процедурного типа PROC = PROCEDURE(): W1 и W2 и две процедуры без параметров: Работа_1 и Работа_2, которые могут использоваться как константы тинпа PROC. Интерпретация (активизация) W1 приведет к вызову Работы_1 и созданию локальной среды (содержащей переменную А). В процессе выполнения Работы_1 производится активизация объекта W2 и соответственно

Занятое прост-а

втоматической

ктивация

При активации каждого нового объекта вершина стека "опуснканетнся вниз" на величину, определяемую размерами локальной среды этого обънекта,- при его пассивации вершина стека "поднимается вверх". С использованием автоматической памяти связаны две оснновнные пронбнлемы: рекурсии и множественности ассоциаций.

Рекурсия - механизм, позволяющий объекту совершать самонакнтинванц-ию. Например, по схеме:

Прямая рекурсия связана с непосредственной повторной (влонжеой) активацией, косвенная - с опосредованной (причем число посннреднников в схеме W1-->...-->W1 может быть произвольным). Иснпольнзонванние рекурсии напрямую связано с размерами рабочего простнранства автонматической памяти. Использование рекурсивных актинваций обънекнтов, с одной стороны, позволяет иметь очень лаконничнные и емкие по сондержанию программы, с другой стороны, в ренкурнсивных схемах (особенно в косвенной рекурсии) возрастает венронятность появления трудно идентифицируемых ошибок.

Множественность ассоциаций заключается в том, что в классе авннтонматической памяти могут быть одновременно размещены неснкольнко однноименных объектов, имеющих в общем случае различные значенния и относящиеся к разным активностям одного и того же или опять-таки разных объектов. В приведенном примере существуют два однонименных объекта: переменная А, связанная (ассоциированная) с активностью W1, и переменная А, ассоциированная с активностью обънекта W2. В соннответствии с принципом стека система пpавления автоматической панмятью всегда pассматpивает в качестве активной поснледнюю созндаую ассоциацию (самую "ближнюю" к вершине стека автонматической панмянти). Возникновение множественности ассоциаций обусловлено только использованием в прикладных программах однонинмеых переменных с различной областью действия (областью виндинмоснти). Если ж иснпольнзонвание таких переменных и является необнхондимым (в чем всегда стонит сомниться), то при их интерпретации следует помнить о мнонженстнвеости ассоциаций.
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄АБvГ  ДqU  Гm╜  ╛h╤  дe└  ╟bе

  ┬

_  Z


Н%О%tс&  т&m='  >'fP'  Q'_0(  1(X3(  4(Qq(  w"  Ы"пппппп
q((vк(  ┤(q╗*  ╩*l/+  N+gS+  T+`я+  
0*0v51  X1qQ9  b9n;  у;kO<  T<fУ<  Я<aY=  v=\OA  
OA_AxyA  ИAu▒B  ╛BpЕC  ЩCk▀C  ьCfTD  eDaУD  жD\3J  
3JCJv~J  ЮJqWK  sKlёL  вLgVN  gNbhN  iN_"O  2OZ+T  
+T;Tv<Tq╥U  ╘Ul┘X  сXg╢\  ╧\bVa  ka]Ъb  ЫbV3c  +T  

3c5ctУc  Фcmf  ff





╪k┘kt


Вupv  zvv
w  1wq╫x  яxlнy  ├yg|z  Иzd┼{  ▄{aF~  b~^BД  [1]
ТТtэТrмЧ  ╦Чp╪Ч  ┘ЧnЧ  √ЧlШ  ШjШ  `ШhbШ  eШfgШ  КШd
КШМШ  еШyжШ  оШw╗Ш  ┌Шu█Ш  ▀ШsуШ  Щq#Щ  MЩoOЩ  RЩm_Щ  ЙЩkНЩ  НЩ╖Щy╣Щ  ╝Щw═Щ  вЩuЪ  ЪsЪ  ^Ъq█Ы  эЫl╫Э  'Юj-Ю  .ЮhЮ  Юf

ЯoЯ  ЯmЯ  XЯkZЯ  ZЯХЯyЧЯ  ╥Яw╘Я  аuа  HаsJа  Баqъл  мl
▒  ╧▒ib┤  n┤fS╢  ZЯ  [1]

╞  ╞Y╞  ╞Rb┤





╞╞  ╞tУ╨  ж╨oЯ╪  ╗╪ju▌  Л▌e╬▌  ▐`Y▀  }▀[

ф  "фX



"фAх  [хxQц  mцsнц  ┬цn╪ш  тшiшш  кшd#щ  :щ_Bщ  PщZы  
  c
sF  
pK  WmZ  fj╠  ┌g+  Cb\  s]
sGНGyЧGt╙G  
Ho║Mm▀MhсMfуMaыM^?N  ╪P\кPYСQ  SWь(
S:SvTtTo)T  █Tm▄T  сMfуMaыM^?N  ╪P\кPYСQ  SWь(
B!7[1] B!7[1] B!7[1] B!7[1] B!7[1] uE

u.u╥u═u‑ЁC?I I TW
Xy+XyэZyX[y[y╗[yт[y[y,\y╫]y?C
╫]а BhshyuhyHiykyкkyмky1lyNly}ly┤ly?C
┤lъlyлmy╥my╧nynyЗoy╕oyGpy[qy?C A{e{yk|yП|y╣|y╩|yЬ}yd~yЯ~yб~y┼yCC
┼tАyАy╖Аy┼Аy№АyБy#Бy)БyхБyуГyCC
уГхГy
ДwДw,Дw.ДwPДwЙДwДwнДwGC ЖЖyнЖyеИwвКw Лw{ОwХПwуПwРwCG СyСylСyэТy+УydУyИУy┤УyCC
┤У╞УyшwЧuЧuoЧsqЧsбЧs═ЧsШsGCIC ЪЪy`ЪybЪyvЫwЫЬw┐ЬwьЬw*ЭwLЭwCG

еyлеy█еy

жy<зyBиyУиyсиy%йyCC
%й[йy│йwйubмsdмqЖмq╜мq╒мqнqCICIC ▒w╧▒u╥▒uCIC?C ~┴Ж├yИ├yн├yр├yв├yz╟yP╩y┤╩yй╦y▄╦y?C
▄╦╠y\╠yФ╠y╠╠y


в╤┤╤y╤╤y▐╤y╥y%╘yS╘yv╘yП╘yн╘y╦╘y?C
╦╘∙╘y╒y╒y,╒yF╒yd╒yВ╒y▓╒y╛╒y└╒y?C
└╒п y▒ y╩ yф y[1] и╫╛╪y-┘ye┘y ┘w
рyOуyhфyнцyIC
нц╪чy2ъyhъyбыy

yU

yn

y╦

y"yFw?C y
yыy╡yрyy╛w╞u$‑uCIC o*В*y╖*y╪*y+yU+yi+yд+y┘+y$,yIC y-а-y╟-yю-y).yb.yЙ.y░.y╫.y№.y!/yIG
!/c/yг/y▄/y0y


e9g9yю<y#?yCy8CyXCyМCyжCy╞CyCyCC
CDyRDyTDyкHyмHy▌Hw
IwQIwПIwGC ┐KбKy-LydLyЫLyнLyуMw?NwiNwаNwCG =жC


п '└-▓4
;A╔GN∙T ZР`jgjl╪r╡xн~ОГКYРЦ╠Ь0дэйепW╡╙╗@┬╞╚r╧З╘х╪а▐#хvыкw

[1] *[1] i[1] e[1]

[[1] <[1] [1]