скачать рефераты
  RSS    

Меню

Быстрый поиск

скачать рефераты

скачать рефератыРеферат: Программирование ориентированное на объекты

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

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

   VAR A: CARDINAL; B: INTEGER;     BEGIN ... A:=B .

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

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

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

       VAR A: INTEGER; B: CARDINAL;

              BEGIN  A:=-3; B:= CARDINAL (A); ...

                    

Здесь 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> :=  
                  VAL (<Имя типа B>, <Объект класса CARDINAL>). 

В качестве типа 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етации на аль­­теp­на­тивной основе.

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

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

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

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

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

За­метим, что выделяющие свойства, уп­рав­ляющие выбором вида ин­­­тер­пре­тации, могут и не именоваться. В таких случаях вид аль­теp­­нативной инте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асши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; .

Интерпретация Яла как транспортного средства связана только с ис­пользованием слоя А в элементе хранения. Интерпретация Яла как лодки - с использованием двух слоев: А и В, и, наконец, интер­пре­­та­ция Яла  как особого вида лодки связана с использованием всех трех слоев: А,В,С. Декларация вида "Структура_Яла" в объектно-ориентированном языке заменяется отношением

            Ял <* Лодка <* Транспортное_Средство.

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

Страницы: 1, 2, 3, 4, 5, 6, 7


Новости

Быстрый поиск

Группа вКонтакте: новости

Пока нет

Новости в Twitter и Facebook

  скачать рефераты              скачать рефераты

Новости

скачать рефераты

© 2010.