на тему рефераты
 
Главная | Карта сайта
на тему рефераты
РАЗДЕЛЫ

на тему рефераты
ПАРТНЕРЫ

на тему рефераты
АЛФАВИТ
... А Б В Г Д Е Ж З И К Л М Н О П Р С Т У Ф Х Ц Ч Ш Щ Э Ю Я

на тему рефераты
ПОИСК
Введите фамилию автора:


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


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

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

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

Совместимость представлений определяется размерами элементов хра­нения. Например, если объекты типа 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ения свойств).

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

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

Пример1.

      TYPE POINT = RECORD X,Y: INTEGER END;

           Point = RECORD Y,X: INTEGER END;

       VAR   A: ARRAY[1..2] OF WORD;

             P: POINTER TO POINT;

             p: POINTER TO Point;

             X,Y: INTEGER;

     BEGIN X:=1; Y:=5;

           P:=ADR(A);                         (*1*)

              P^.X:=X; P^.Y:=Y;               (*2*)

           p:=ADDRESS(P);                     (*3*)

              X:=p^.X; Y:=p^.Y                (*4*)

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

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

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

    VAR C: ARRAY [1..100] OF CARDINAL;

        P: POINTER TO ARRAY [1..200] OF CHAR;

        CH: ARRAY [1..200] OF CHAR;

    BEGIN                                                                                                                                                                  

      P := ADR(C); FOR I:=1 TO 200 DO CH[I]:=P^[I] END;...

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

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

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

          TYPE Действие = PROCEDURE (Станок);

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

               PROCEDURE Включить (С: Станок);

               PROCEDURE Выключить (С: Станок); .

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

               VAR D: Действие; C: Станок;

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


на тему рефераты
НОВОСТИ на тему рефераты
на тему рефераты
ВХОД на тему рефераты
Логин:
Пароль:
регистрация
забыли пароль?

на тему рефераты    
на тему рефераты
ТЕГИ на тему рефераты

Рефераты бесплатно, реферат бесплатно, курсовые работы, реферат, доклады, рефераты, рефераты скачать, рефераты на тему, сочинения, курсовые, дипломы, научные работы и многое другое.


Copyright © 2012 г.
При использовании материалов - ссылка на сайт обязательна.