![]() |
![]() |
Altair |
![]()
Сообщение
#1
|
![]() Ищущий истину ![]() ![]() ![]() ![]() ![]() ![]() Группа: Модераторы Сообщений: 4 824 Пол: Мужской Реальное имя: Олег Репутация: ![]() ![]() ![]() |
Один из подходов в программировании носит название: "Объектно-ориентированное программирование" или, сокращенно, ООП. Идея этого подхода заключается в стремлении связать данные с обрабатывающими эти данные процедурами в единое целое - ОБЪЕКТ.
В Турбо Паскале ООП реализовано начиная с версии 5.5. ООП основано на трех важных принципах, придающих объектам особые свойства и отличающих их от других типов данных. Рассмотрим их:
Сначала может показаться, что при описании нет разницы между объектами и записями. На деле разница заключается в том, что при описании объекта в него могут входить заголовки процедур и функций, ведь по определению объект это "Данные+Алгоритмы". Перефразируя Вирта, можно сказать что: "Алгоритмы+Структуры Данных=Объекты". Выглядит описание объекта так: type Переменные, описанные в объекте называются полями, а процедуры их обработки - методами. В самом типе объекта описан лишь интерфейс метода (так же, как при написании модуля в разделе INTERFACE мы описываем только заголовки), т.е. способ его вызова. Сам метод описывается в разделе процедур и функций, и заголовок имеет нестандартную форму (перед его именем обязательно указывается имя типа объекта, к которому этот метод принадлежит): procedure ObjectType.ProcedureName(...); Т.е <имя_объекта>.<имя_процедуры> Параметры описываются как обычно, за исключением того, что внутри метода всегда доступны поля объекта непосредственно по их именам. Например: type Так как задание заголовка метода в описании типа объекта является опережающим описанием, то так же, как при реализации процедур и функций в разделе IMPLEMENTATION, список параметров может опускаться, то есть, такое описание будет полностью аналогично предыдущему: procedure TA.give; Переменные типа "объект" можно создавать как обычно, объявлением в списке переменных (при таком способе для использования экземпляров объектов - переменных объектного типа - в программе, их вызывают так: <имя_объекта>.<имя_метода>): type TA = object ... end; но большее распространение получил метод их размещения в динамической памяти. Для этого нужно создать дополнительный тип - указатель на объект (в таком случае для обращения к полям или методам объекта указатель надо разыменовать): type Наследование При описании объекта-наследника (также называемого производным типом), имя его родителя указывается в скобках. Например: TA = Поля и методы родителя могут появляться в реализации методов наследника, как если бы они были описаны явно в самом наследнике. Процесс наследования является транзитивным: если TB наследуется от TA, а TC в свою очередь - наследник TB, то тип TC также считается наследником TA. Следует обратить внимание на то, что при наследовании полей в производном типе нельзя объявлять идентификаторы, которые уже использовались в одном их типов-родителей. (На методы это ограничение не распространяется, в случае повторного определения метода он считается переопределенным, и ко всем потомкам будет переходить именно переопределенный метод.) Из "умения" объектов "наследовать" вытекает правило присваивания для переменных типа "Объект": переменным такого типа можно присваивать не только значения этого же типа, но и значения любого производного типа. Например, при таком определении: type для копирования значения X записанного в переменной b в переменную a достаточно выполнить присваивание: a := b; Внимание: Операция присваивания возможна только таким путем: "Родитель <-- Наследник" При этом гарантируется заполнение всех полей типа "Родитель" содержимым соответствующих полей типа "Наследник", так как в "Наследнике" число полей не меньше, чем в родителе. В противном случае могла бы возникнуть неопределенность с "лишними" полями, которых нет в "Родителе". Операцией присваивания копируются только поля. Методы таким образом не присваиваются... Использование объектов Посмотрим теперь на практике, как работать с объектами. uses crt; Итак, рассмотрим эту программу. Это первая наша программа с объектами. В ней есть 2 объекта - родитель Т1 и потомок Т2. Я специально сделал так, чтобы в них были методы (процедуры) с одинаковыми именами. Обратите внимание, что мы не описывали в Т2 процедуру Vec, однако, при вызове: c.Vec метод заработал. Это произошло, потому что объект T2 является потомком Т1, и он знает все методы и данные своего родителя Т1. И наоборот Т1 не знает, что есть процедура Summ. На этом примере мы также убедились, что при перекрытии работает тот метод, который был описан позднее (т.е. метод потомка, а не родителя). То есть при вызове C.Print пошла запись в файл, а не на экран монитора, как есть в методе родителя. Таким образом, при наследовании объект-потомок наследует все методы родителя и перекрывает одноименные. |
![]() ![]() |
Altair |
![]() ![]()
Сообщение
#2
|
![]() Ищущий истину ![]() ![]() ![]() ![]() ![]() ![]() Группа: Модераторы Сообщений: 4 824 Пол: Мужской Реальное имя: Олег Репутация: ![]() ![]() ![]() |
Пойдем дальше.
Итак, мы научились создавать простейшие объекты, и объекты потомки, теперь посмотрим для чего нужны директивы Public и Private. Создадим простую базу данных "Книги", в которая хранит информацию в типизированном файле, а поля записи следующие:
(Кодировка текста программы - Cyrillic Win, так что для использования программы Вам придется перекодировать текст в ДОС. Я специально сделал кодировку WIN, чтобы все объяснения делать прямо в программе используя коментарии): Исходный код Unit DateBase; Interface Uses CRT; Type BOOK = record NAME : string[30]; TOM : string[2]; autor : string[30]; IO : string[2]; { инициалы } INFO : string[30]; { доп.информ. } GEO : string[30] { расположение } end; BD= object Private BDF: file of BOOK; BDFileName:string; Function UpStr(s:string):string; Procedure Add; Procedure PrintCRT; Procedure Search; Public Procedure Run; Procedure Init; Procedure Done; end; Implementation {------- теперь опишем методы------} Procedure BD.Init; { подготовка к работе } begin If paramcount=0 then BDFileName:='C:\BOOKH.BD' else BDFileName:=paramstr(1); TextColor(Black); TextBackGround(7); ClrScr; Assign(BDF,BDFileName); {$I-} Reset(BDF); {$I+} If IOresult=0 then begin Seek(BDF,0); Exit end else rewrite(BDF) end; {-----------------------------------------------} Procedure BD.Done; { завершение работы } begin CLOSE(BDF); NormVideo; TextBackGround(0); ClrScr; HALT(1) end; {-----------------------------------------------} {Эта функция взята из программы PWLHack, старой прогрммы для взлома PWL, она хороша тем, что максимально оптимизирована } Function BD.UpStr(S:String):String; {перевод строки в верхний регистр} Var I:Byte; Begin For I:=1 To ORD(S[0]) Do Begin Case S[I] Of 'a'..'z':S[I]:=Chr(Ord(S[I])-$20); 'а'..'п':S[I]:=Chr(Ord(S[I])-$20); 'р'..'я':S[I]:=Chr(Ord(S[I])-$50) End End; UpStr:=S End; {-----------------------------------------------} Procedure BD.Add; { Добавление элементов } Var POLE:book; Begin ClrScr; GOTOXY(30,10); Write('Введите название книги:'); repeat GOTOXY(25,11); Readln(POLE.NAME) until pole.name<>''; GOTOXY(30,12); Write('Введите номер тома:'); GOTOXY(25,13); Readln(POLE.TOM); GOTOXY(30,14); Write('Введите фамилию автора:'); repeat GOTOXY(25,15); Readln(POLE.autor) until pole.autor<>''; GOTOXY(30,16); Writeln('Введите инициалы автора:'); GOTOXY(25,17); Readln(POLE.IO); GOTOXY(30,18); Writeln('Дополнительная информация о книге:'); GOTOXY(25,19); Readln(POLE.INFO); GOTOXY(30,20); Writeln('Где находится эта книга'); repeat GOTOXY(25,21); READln(POLE.GEO) until pole.geo<>''; GOTOXY(35,24); Writeln('ЗАПИСЫВАЮ ...'); {------------------------} Seek(BDF,FileSize(BDF)); Write(BDF,POLE); GOTOXY(35,25); Writeln('ЗАПИСАЛ.') end; {-----------------------------------------------} Procedure BD.PrintCRT; { печать на экран содержимого файла } var i:longint; POLE:BOOK; begin ClrScr; For i:=0 to FileSize(BDF)-1 do begin Seek(BDF,i); read(BDF,POLE); writeln('---------------------------'); writeln('Название: ',POLE. NAME); If POLE.TOM<>'' then writeln('том: ',POLE.TOM); writeln('Автор: ',POLE.autor); If POLE.IO<>'' then writeln('Инициалы: ',POLE.IO); If POLE.INFO<>'' then writeln('Доп.Информ: ',POLE.INFO); writeln('Расположение: ',POLE.GEO); writeln('---------------------------'); If (i+1) mod 3 = 0 then begin GOTOXY(20,25); Write('Нажмите клавишу ENTER для продолжения'); readkey; clrscr end End; Write('Нажмите клавишу ENTER для продолжения'); readkey end; {-------------------------------------------------------} Procedure BD.Search; {Поиск записи } var i:longint; POLE:BOOK; param1,param2,param3, param4,param5,param6:string; begin ClrScr; GOTOXY(30,10); Write('Введите название книги:'); GOTOXY(25,11); Readln(param1); GOTOXY(30,12); Write('Введите номер тома:'); GOTOXY(25,13); Readln(param2); GOTOXY(30,14); Write('Введите фамилию автора:'); GOTOXY(25,15); Readln(param3); GOTOXY(30,16); Writeln('Введите инициалы автора:'); GOTOXY(25,17); Readln(param4); GOTOXY(30,18); Writeln('Дополнительная информация о книге:'); GOTOXY(25,19); Readln(param5); GOTOXY(30,20); Writeln('Где находится эта книга'); GOTOXY(25,21); Readln(param6); ClrScr; For i:=0 to (FILESIZE(bdf)-1) do begin seek(bdf,i); read(bdf,pole); If (UPSTR(pole.name)=UPSTR(param1)) or (UPSTR(pole.TOM)=UPSTR(param2)) or (UPSTR(pole.autor)=UPSTR(param3))or (UPSTR(pole.io) = UPSTR(param4)) or (UPSTR(pole.info)=UPSTR(param5)) or (UPSTR(pole.geo)=UPSTR(param6)) then begin Writeln('-----------------------'); Writeln('Найденно: '); write('Название: '); writeln(pole.name); if pole.tom<>'' then begin write('Том : ');writeln(pole.tom) end; write('Автор :'); writeln(pole.autor); write('Инициалы:'); writeln(pole.io); write('коментарий- '); writeln(pole.info); write('расположение:');writeln(pole.geo); writeln('---- для продолжения поиска нажмите любую клавишу ...'); readkey end end end; {-------------------------------------------------------} Procedure BD.Run; const p=true; var c:byte; x,y:integer; begin repeat ClrScr; textbackground(2); gotoxy(30,6); write('1. Ввод данных'); gotoxy(30,8); write('2. Вывод данных на экран'); gotoxy(30,10); write('3. Поиск данных'); gotoxy(30,14); write('4. Выход'); textbackground(7); while not keypressed do; c:=ORD(readkey); If c=49 then add; If c=50 then printCRT; If c=51 then Search; If c=52 then BD.DONE until p=false; end; End. Теперь напишем программу для тестирования этого модуля: Uses DateBase; Все отлично работает. Теперь попробуем не запуская всю программу (базу данных), просто проверить, работает ли метод PrintCRT. Пишем программу: Uses DateBase; Запускаем... Ой, ошибка! Error 44. А почему? А вот почему: Посмотрите внимательно на наш объект, там есть два зарезервированных слова Public и Private. Это директивы. Рассмотрим их действие. Директива Private в описании объекта открывает секцию описания скрытых полей и методов. Перечисленные в этой секции элементы объекта "не видны" программисту, если этот объект он получил в рамках библиотечного модуля (TPU). Скрываются обычно те поля и методы, к которым программист не должен иметь непосредственного доступа. В нашем примере это процедуры (т.е. методы) ввода, вывода и сами данные. Директива Public отменяет действие директивы Private, поэтому все следующие за Public элементы объекта доступны в любой программной единице. По умолчанию устанавливается тип доступа Public. Соответственно мы можем в нашей программе описать тип объекта-потомка, в котором можем перекрыть любой метод. Думаю с директивами Public и Private все стало ясно. -------------------- Помогая друг другу, мы справимся с любыми трудностями!
"Не опускать крылья!" (С) |
![]() ![]() |
![]() |
Текстовая версия | 26.07.2025 0:19 |