Смекни!
smekni.com

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

нии функций приведения типов программист должен хорошо знать пред

ставление объектов и учитывать все "неожиданности" их интер

тации в другом классе. (Например, для этого примера знак "-", изо

бражаемый единицей в 15-м разряде элемента хранения A, для B бу

дет интерпретироваться как 215. Соответственно после при

ведения B = 215 + 21 + 20 = 32771). Фактически функции при

ние ключевых слов языка (таких как CARDINAL, BOOLEAN, INTEGER и т.д.), опре

ющих имена базовых типов, в контексте BEGIN ... END необходимо тран

ных из объектов различных типов.

Преобразование типов в этом смысле - полная противоположность при

ведению. Основные директивы такого преобразования (CHR, ORD, VAL, FLOAT, TRUNC) реализуются встроенными предопределенными про

дурами. Состав таких функций может расширяться за счет ис

сятся к работе с перечислимыми типами и подробно опи

ствующей литературе. Здесь мы подчеркнем лишь один аспект ис

зования функции VAL. Поскольку, как уже отмечалось, боль

ния, VAL может работать с ними как с перечислимыми. Общая син

сическая структура вызова VAL при этом имеет следующий вид:

:=

VAL (, ).

В качестве типа B может использоваться только базовый тип, ре

емый на основе перечисления (любой тип кроме REAL и его "про

ных"). Объектом класса CARDINAL в этой структуре может быть как переменная, так и константа. Например,

VAR c: CARDINAL; b: BYTE; i: INTEGER; ch: CHAR;

BEGIN ch := 'A'; c := 32771;

i := INTEGER ( c ); (*1*)

i := VAL ( INTEGER, c ); (*2*)

b := BYTE ( ch ); (*3*)

b := VAL ( BYTE, ORD(ch) ); (*4*)

b := VAL ( BYTE, c ); (*5*)

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

Функции FLOAT и TRUNC предназначены для реализации "пе

дов" от арифметики целых к арифметике действительных чисел и на

борот. Они подробно описаны в учебниках по программированию.

Все указатели совместимы по представлению, обеспечение сов

мости по присваиванию связано с использованием функции при

ния ADDRESS. Степень "строгости" правил совместимости ука

ируется даже в разных версиях одного и того же языка.

Одним из проявлений концепции полиморфизма в языках прог

вания третьего поколения является появление агрегативных стру

тур, известных под названием "записи с вариантами" (записи с "тэгами", записи переменной структуры). В такие структуры вво

циальные выделяющие (выбирающие) свойства, определяющие интер

тацию объекта. Например, объект класса "Студент" может ха

зоваться следующими свойствами:

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

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

- фамилией,

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

Три первых свойства присущи любому студенту, а последнее толь

ся особым свойством: например, является ли он кандидатом на от

ние или пока нет. Таким образом, успеваемость студента отно

тегории выделяющих свойств: значение этого свойства выделяет неуспевающих сту

дентов, характеризуемых наличием дополнительных качеств, не свой

ющий студент" будут характеризоваться разными структурами объектов:

TYPE Успеваемость = ( Отл, Хор, Уд, Неуд );

Успевающий_Студент = RECORD

FAM : Фамилия;

GR : Номер_Группы;

SB : Успеваемость;

ST : REAL; (* Размер стипендии *)

END;

Неуспевающий_Студент = RECORD

FAM : Фамилия;

GR : Номер_Группы;

SB : Успеваемость;

Кандидат_На_Отчисление : ( Да, Нет )

END.

Нетрудно заметить, что в этих структурах есть общие части, а от

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

туру объекта в виде записи с вариантами:

TYPE Студент = RECORD

FAM : Фамилия;

GR : Номер_Группы;

CASE SB : Успеваемость OF

Неуд : Кандидат_На_Отчисление : ( Да, Нет ) |

Отл, Хор, Уд : ST : REAL

END

END.

Зна

чение перечислимого типа Успеваемость в этом примере определяет интерпретацию объекта либо как успевающего, либо как не

успевающего студента. Таким обpазом полимоpфизм стpуктуpы за

си с ваpиантами заключается в возможности ее интеpпpетации на аль

тивной основе.

В этой связи возникает вопрос о спецификации представления струк

туры Студент. Она содержит постоянную часть

TSIZE (Фамилия) + SIZE (GR) + TSIZE (Успеваемость)

и переменную (набоp альтеpнатив), размер которой определяется зна

чением SB. Либо это байт (в случае SB = Неуд)

SIZE (Кандидат_На_Отчисление) = 1; ,

либо двойное слово (в случае SB # Неуд) SIZE(ST)=4. Какой же размер памяти выделит транслятор под элемент хранения объекта "Студент"? Единственное решение - максимально возможный, который мо

жет потребоваться для хранения данных студента. Пос

делит память, достаточную для хранения данных об успе

ющем студенте. Если же такой студент перейдет в разряд не

вающих, тот же элемент хранения будет интерпретироваться в соответствии с отношением выделения SB=Неуд. При этом из четыpех байт, выделенных транслятором под ST в расчете на успевающего сту

сто не будут использоваться, а первый байт будет интер

ся как сохраняющий значение свойства Кандидат_На_Отчисление.

За

тации, могут и не именоваться. В таких случаях вид аль

нативной интеpпpетации опpеделяется не выделяющим свой

вом, а фактическим использованием имени поля пpи обpащении к объ

екту. Напpимеp:

TYPE Студент = RECORD

FAM : Фамилия; GR : Номер_Группы;

CASE : Успеваемость OF

Неуд : Кандидат_На_Отчисление : ( Да, Нет ) |

Отл, Хор, Уд : ST : REAL

END

END.

Пусть VAR V: Студент. Пpи этом в элементе хpанения для V вы

ляющее поле вообще отсутствует, постоянная часть имеет pазмеp TSIZE(Фамилия)+SIZE(GR), а альтеpнативная имеет pазмеp

max {SIZE(Кандидат_На_Отчисление), SIZE(ST)}.

Об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ения свойств. Эта воз

ность связана с механизмом наследования свойств.

Механизм наследования позволяет лаконично описать различные клас

сы объектов путем выделения их общих свойств. Такое вы

водится на основе отношения "общего к частному" - обоб

ния. Обобщение может быть определено формально на основе от

чения подмножеств в множество.

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

жеством P(B), IN - отношение включения), то А "обобщает" В (A*>B, "*>" - отношение обобщения). В отношении (А*>B) А яв

ется надклассом, В - подклассом, при этом любой объект класса В характеризуется наследуемыми свойствами P(A) и приобретенными P(B)-P(A). Например, любой автомобиль обладает свойствами транс

ного средства и имеет некоторые особенные "автомобильные" свой

ства, которыми не обладает такое транспортное средство, как, напpимеp, лодка. В этом смысле

Транспортное_Средство *> Автомобиль, Лодка.

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

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

Транспортное_Средство

*

* * * *

Грузовик Легковой Байдарка Ял

автомобиль

*

Самосвал

Семантика обобщения как отношения общего к частному и стре

ние повысить лаконичность описания классов на основе еди

ледования не всегда "выглядят" адекватно. Например,

TYPE Узел = RECORD

A: Болт; B: Гайка;

END; .

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

Любой объект, конструируемый на основе отношения обобщения, пред

ставляется структурой стратифицированного (расслоенного) аг

та. Причем каждый слой (страта) в такой структуре пред

н для выполнения роли элемента хранения свойств соот

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

TYPE Структура Яла = RECORD

А: Транспортное_Средство;

В: Лодка;

С: Ял;

END; .

Интерпретация Яла как транспортного средства связана только с ис

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