Смекни!
smekni.com

Программирование ориентированное на объекты (стр. 4 из 10)

TYPE Дата_рождения = RECORD

Г: Год; М: Месяц; Д: День

END;

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

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

WITH < Квалидент > DO < Присоединяемый фрагмент > END.

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

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

WITH A DO

<Работа со атpибутами объекта A через имена B и П>;

WITH B DO

<Работа со атpибутами свойства В объекта А

через имена Г,M,D>

END

END.

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

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

VAR A,B: Объект; C: Год;

BEGIN . . .

┌─ WITH A DO

(1) │ WITH B DO C:=Г END; B.B.Г:=C

└─ END . . .

┌─ WITH A DO

(2) │ WITH B DO C:=Г; B.Г:=C END

└─ END . . .

┌─ WITH A DO

│ WITH B DO C:=Г END

│ END;

(3) │

│ WITH B DO

│ WITH B DO Г:=C END

└─ END.

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

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

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

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

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

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

TYPE Стрелка = POINTER TO Объект;.

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

TYPE ADDRESS = POINTER TO WORD.

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

TSIZE (ADDRESS) = TSIZE (WORD) = 2 (байта).

Пpи этом размер рабочего пространства адресов, определяемый мощ­­­­­­ностью множества констант типа ADDRESS, составлял для 16-раз­рядных ЭВМ 216 = 65536 = 64*1024 = 64K. Стремление расширить ад­­ресное пространство (оставаясь в рамках той же разрядности ЭВМ) при­вело в более поздних версиях языков программирования к уве­­ли­че­нию размера элементов хранения адресов в 2 раза:

TSIZE (ADDRESS) = TSIZE (ARRAY[1..2] OF WORD) = 4 (байта).

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

TYPE ADDRESS = RECORD

SEGMENT, OFFSET: CARDINAL;

END;

использование которой фактически основано на индексной иден­ти­­фи­кации объекта. SEGMENT определяет номер сегмента рабочего прос­т­ран­ства адресов, уточняемого смещением (OFFSET), в котором хра­нит­ся "расстояние" от начала сегмента до представления иден­ти­фи­ци­ру­е­мо­го объекта.

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

TYPE Квадрат: ... ; VAR P: POINTER TO Квадрат;

Элемент xранения указателя

┌─────────────────────────────┐

Имя: P │ Значение указателя *──┼───┐ (P=NIL)

└──────────────────────────┼──┘ v

┌───┬─────┬────────┬────┘ ─┴─

│ │ │ ─┼─

│ │ │ │

┌──v───┼─────┼────────┼───────┐

│ ┌┴┐ │ │ v │ ┌─┐ объект класса

│ └─┘ v v ░░░ │ └─┘ Квадpат

│ ┌┴┐ ┌┴┐ │

│ └─┘ └─┘ │ ░░░ объект класса

│ │ Pешето

│ Pабочее пpостpанство памяти │

└─────────────────────────────┘

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

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

TYPE Элемент_Фигуры = RECORD

A : Квадрат;

B : POINTER TO Элемент_Фигуры

END.

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

┌────────┐ ┌──────────┐

│ v v P │ v

│ ┌───┴───┐ ┌───┴───┐ │ ┌───┴───┐

│ │ A │ │ A │ │ │ A │

│ │───────┤ ├───────│ │ ├───────│

│ │ B *─┼────────>┤ B *─┼─────┘ │ B * │

│ └───────┘ └───────┘ └───┼───┘

│ │

└───────────────────────────────────────────────┘

VAR P: POINTER TO Элемент_Фигуры

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

Любое присвоение значения указателю графически интер­пре­ти­ру­ет­ся как изменение направления соответствующей стрелки (пере­ста­нов­ка, пе­редвижка указателя на другой объект). Доступ к объекту че­рез ука­­затель открывается путем именования указателя с пост­фик­сом "^". Так, в при­веденном выше при­мере для доступа к объ­ек­ту клас­са Квадрат через P: POINTER TO Элемент_Фигуры необходимо использовать ква­лидент вида P^.A. В нем "зашифрована" следующая пос­ледо­ва­тель­ность доступа: