Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Лекции 26-27: Объекты и объектно-ориентированное программирование




End

Else with r^ do

if ch<c then insert_tree(left,ch) else

if ch>c then insert_tree(right,ch) else count:=count+1;

end {insert_tree};

procedure print_tree(r:link); {Печать количества вхождений букв }

begin if r<> nil then with r^ do

begin print_tree(left);writeln(c,':',count); print_tree(right) end

end {print_tree};

procedure search_tree(r:link;ch:char); {Поиск ch и печать}

begin if r= nil then writeln(ch,':0') else with r^ do

begin if ch<c then search_tree(left,ch) else

if ch>c then search_tree(right,ch) else writeln(ch,':',count)

end {search_tree};

BEGIN L:=['A'..'Z']; root:= nil;writeln(' Введите текст:'); while not eof do

begin readln(s); for j:=1 to length(s) do

begin if upcase(s[j]) in L then insert_tree(root,s[j]) end;

end; writeln('СПРАВКА ПО ЧАСТОТАМ ЛАТИНСКИХ БУКВ:');

while not eof do begin readln(symb);search_tree(root,symb) end;

write('Печатать по всем буквам?(Y/N)');readln(symb);

if symb<>'N' then print_tree(root);

END {frequency_letters}.

1.Принципы объектно-ориентированного программирования.

2. Концепция объекта в Турбо Паскале.

3. Свойства наследования и полиморфизма объектов.

4. Пример программы с использованием объектов.

5. Понятие о динамических объектах.

6. Расширенное использование процедуры new.

7. Освобождение хип-памяти от динамических объектов.

1.Принципы объектно-ориентированного программирования.

Традиционным направлением развития программирования в течение многих лет было так называемое процедурное программирование, в основе которого лежит понятие процедуры (подпрограммы). В соответствии с этим направлением сложная программа строится из более мелких частей - процедур, осуществляя декомпозицию задачи на подзадачи и преодолевая сложность исходной задачи. Однако по мере увеличения сложности задачи растёт число процедур, и их использование требует (начиная от некоторого предела) собственной поддержки. Замечено, что если при процедурном подходе длина программы становится больше 1000-1500 строк, существенно возрастает сложность отладки такой программы. Таким образом, возникла потребность в качественно новом подходе в программировании. Этим подходом стало объектно-ориентированное программирование.

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

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

Объектно-ориентированное программирование не отрицает процедурный подход, а лишь поднимает его на более высокий уровень. Инкапсуляция - это декомпозиция процедур по функциональному принципу, вносящая существенную упорядоченность в использование процедур. Выигрыш от использования объектно-ориентированного подхода, тем выше, чем сложнее программа. В настоящее время многие программы строятся на базе объектно-ориентированного подхода, а для построения пользовательского интерфейса объектно-ориентированный подход является общепризнанным (он использован, в частности, в системах Turbo Vision и DELPHI).

 

2. Концепция объекта в Турбо Паскале.

В языке Турбо Паскаль (начиная с версии 5.5) введено новое понятие объекта, как дальнейшее развитие концепции типа. Как и типы, объекты должны быть описаны в разделе описаний программы. Форма описания объекта аналогична описанию типа Запись. Различие лишь в том, что ключевым словом описания является object, а не record, и кроме обычных полей (элементов структуры данных) в описании объекта используются процедурные поля - заголовки процедур и функций, инкапсулированных в данном типе объекта. Кроме того, возможности описания полей структуры данных расширены - могут описываться кроме переменных также необходимые типы данных, константы. Переменные, образующие структуру данных, называются полями объекта, а процедуры и функции - методами объекта. При этом тела методов должны быть описаны вне описания объекта: обычно в соответствующих модулях.

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

Пример описания объекта:

type point = object; {объект - точка на плоскости}

x,y: integer; {координаты точки}

c: byte; { цвет точки}

vis: boolean; { светимость}

procedure create(a,b:integer); {создание точки}

procedure move(dx,dy:integer); {сдвиг точки}

procedure setcolor(color:byte); {установка цвета}

procedure vis_on; {включить светимость}

procedure vis_off; {выключение светимости}

function getX:integer; {получить координату Х}

function getY:integer; {получить координату Y}

end {point};

Для работы с объектами помимо описания объекта, как и при описании других типов, необходимо объявить переменные типа объект, называемые экземплярами объектов. Например, для описанного выше объекта point можно объявить экземпляры: var p1,p2:point; {две точки}

Для обращения к полям и к методам объекта используются составные имена (имена с точкой), аналогично тому, как это принято для записей. Например: p1.X:=1; p1.Y:=p1.X; p2.X:=p1.getX; p1.SetColor(green);

 

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

 

Аналогично записям, доступ к полям и методам объекта можно упростить за счет использования оператора with.

Например: with p1 do begin x1:=getX; y1:=getY end;

Для объектов одного типа допустимо присваивание, например: p1:=p2;

 

3. Свойства наследования и полиморфизма объектов.

Инкапсуляция, хотя и вносит определенный порядок в использование данных и процедур, однако не уменьшает их количества, т.к. определяет только правила использования собственных средств, сосредоточенных в капсуле.

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

Любой объект может быть объявлен потомком ранее описанного объекта-предка. При этом объекту-потомку становятся доступны все методы своего предка и все структуры данных этого предка. Кроме того, объект-потомок вправе определить свои дополнительные поля и методы и даже перекрывать методы предка. Каждый объект имеет единственного предка (непосредственного), а каждый предок может иметь любое число потомков. Это обычные правила иерархии.

Свойство наследования распространяется по цепочке, образуя дерево родственных объектов. В этом дереве имеется один объект-корень, являющийся предком всех других объектов. Если иерархия хорошо продумана, то получается библиотека объектов, представляющая многообразие связанных объектов, используемых при разработке прикладных программ. Примером такой библиотеки является Turbo Vision - библиотека объектов для разработки текстовых интерфейсов в системе DOS.

В Турбо Паскале, чтобы объявить объект потомком некоторого объекта-предка необходимо после ключевого слова object в круглых скобках указать имя объекта-предка. При этом в описании объекта-потомка указываются только дополнительные поля и методы, отсутствующие у предка (или предков). Например:

type Line = object (point); {объект- Линия, являющийся предком объекта point}

xe,ye:integer; {координаты точки-конца линии}

procedure set_line(x1,y1,x2,y2:integer);{установка линии}

procedure get_line(var x1,y1,x2,y2:integer); {получить координаты }

end {Line};

Для экземпляров объектов Line доступны все поля и методы объекта point и, кроме того, поля координат второй точки (Хе и Ye), а также методы set_line и get_line.

Оператор присваивания может быть использован для обмена информацией между родственными объектами. Однако допустим только односторонний обмен - от потомка к предку. Например, если объявить L1 как экземпляр объекта Line, то допустимо присваивание вида p1:=L1; но не наоборот.

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

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

Статическое перекрытие - объявление для объекта-потомка нового метода с тем же именем и, если необходимо, с тем же набором параметров, что и у метода, объявленного для предка. В этом случае новый метод, согласно принятому в Турбо Паскале обычному "правилу действия имён" (которое мы рассматривали ранее, при описании механизма процедур), будет действовать таким образом, что "видимым " для объекта-потомка и всех его потомков будет новый метод, в то время как для объекта-предка будет действовать старый метод (недоступный теперь для объекта-потомка!). Такой механизм перекрытия недостаточно гибкий и имеет распространение только в одном направлении - к потокам. Более гибким является специально введенный для объектов механизм динамического перекрытия.

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

Фактическое связывание объекта с методами (полями объекта) осуществляется при обращении к конструктору - специальному методу, который отличается от обычного метода лишь ключевым словом constructor, заменяющим ключевое слово procedure. При наличии виртуальных методов в описании объекта должен присутствовать хотя бы один конструктор. В момент обращения к конструктору в специальное поле объекта заносится адрес нужной таблицы виртуальных методов, в результате чего все виртуальные методы оказываются связанными с экземплярами объектов, и получают доступ к нужным полям. Таким образом, полиморфизм распространяется не только вниз к потомкам, но и вверх - к предкам.

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

4. Пример программы с использованием объектов.

Программа с использованием объектов на Турбо Паскале построена как демонстрация работы кода с исправлением ошибки в одном символе сообщения (кода Хэмминга). В этой программе использованы два модуля: модуль fbyte (аналогичный рассмотренному ранее модулю f_byte) и модуль cod_Hem, содержащий объекты: символ и строка символов (Tsymb и Tstr_symb). Программа имеет следующий вид:

program Hamming;{демонстрация кода Хэмминга}

uses CRT,Cod_Hem, Fbyte;

var msg: string [22]; {исходная строка-сообщение}

source:Tstr_symb;{объект- строка символов вывода}

r:byte;{позиция искажённого символа}

er_msg: string;{строка, переданная по каналу}

s1,s2: string;{подстроки er_msg}

X,D1,D2:byte;{контроль принятого сообщения}

s: string;{строка-Nпоследнего символа}

symb:char;{исправленный символ}

BEGIN TextColor(Yellow);TextBackground(white);ClrScr;writeln('Исходная строка:');

gotoXY(5,2);read(msg); gotoXY(5,2); with source do

begin {Вывод исходного сообщения} if length(msg)<10 then

repeat insert(' ',msg,1) until length(msg)=10;

put_str(msg,green,100);gotoXY(1,3);

{Кодирование исходного сообщения}

writeln('Кодирование:');readkey;gotoXY(5,4);

put_bstr(msg,brown,100);gotoXY(5,7);

codK1(msg);write(msgK1);gotoXY(Xc,Yc);

put_bsym(chr(K1),magenta);gotoXY(5,8);

codK2(msg);write(msgK2);gotoXY(Xc,Yc);

put_bsym(chr(K2),magenta);delay(1000);

{Передача сообщения и моделирование ошибки}

gotoXY(1,9);write('Передача по каналу с шумом:');readkey;

gotoXY(5,10);er_msg:=msg+chr(K1)+chr(K2);randomize;

r:=random(length(er_msg)+1); if r<>0 then

begin if r<>1 then s1:=copy(er_msg,1,r-1) else s1:='';

er_msg:=copy(er_msg,r+1,length(er_msg));

end else s1:='';

if r<>0 then begin if r<>1 then put_bstr(s1,cyan,100);gen_sym(red);

delay(1000);change_c(cyan);s1:=s1+c;

end; if er_msg<>'' then put_bstr(er_msg,cyan,100);

delay(1000);gotoXY(1,13);

{Приём сообщения и контроль ошибок}

writeln('Принятое сообщение:');readkey;gotoXY(5,whereY);

er_msg:=s1+er_msg;put_str(er_msg,blue,100);

D2:=ord(er_msg[length(er_msg)]);gotoXY(2,16);

er_msg:=copy(er_msg,1,length(er_msg)-1);

codK1(er_msg);D1:=K1;delete(msgK1,length(msgK1)-10,6);

msgK1:='D1='+msgK1;write(msgK1);gotoXY(Xc-3,Yc+1);write('D1');

gotoXY(Xc-3,Yc+2);put_bsym(chr(D1),red);delay(500);

gotoXY(2,17);er_msg:=copy(er_msg,1,length(er_msg)-1);

codK2(er_msg);D2:=fplus(K2,D2);msgK2:='D2='+msgK2;

delete(msgK2,length(msgK2)-9,10);str(length(er_msg),s);

msgK2:=msgK2+'+C'+s;write(msgK2);gotoXY(Xc,Yc-1);

write('D2');gotoXY(Xc,Yc);put_bsym(chr(D2),red);

gotoXY(2,Yc+2); if (D1=0) and (D2=0) then

put_str('Ошибок нет',green,100);

if (D1=0) and (D2<>0) then put_str('Ошибка в K2',red,100);

if (D1<>0) and (D2=0) then put_str('Ошибка в K1',red,100);

if (D1<>0) and (D2<>0) then

begin put_str('Ошибка!',red,100);gotoXY(2,Yc+1);

{Вычисление ошибочной позиции и исправление ошибки}

write('Коррекция ошибки:');readkey;fequat(D1,D2,X,r);

writeln(' D1*X=D2; r=L-log2_(X)+1; L-длина сообщения ');

write(' Вес ошибки X= ');put_str(b_str3(X),red,100);

write(' Номер ошибочной позиции r= ');r:=length(msg)-r+1;

put_str(b_str3(r),red,100);gotoXY(2,Yc+1);

writeln('Конечное сообщение:(исправление C',r,'+D1)');

gotoXY(5,Yc+2);put_bstr(copy(er_msg,1,r-1),blue,100);

put_bsym(er_msg[r],red);delay(1000);gotoXY(Xc-3,Yc);

symb:=chr(fplus(ord(er_msg[r]),D1));

put_bsym(symb,blue);er_msg[r]:=symb;

put_bstr(copy(er_msg,r+1,length(er_msg)),blue,100);

gotoXY(5,Yc+3);put_str(er_msg,green,100);

end else begin writeln;

writeln(' Конечное сообщение:');gotoXY(5,whereY);

put_str(er_msg,green,100) end;

end;readkey

END {Hamming}.

 

Модуль, используемый в программе Hamming:

UNIT cod_Hem; {объекты для демонстрации кода Хэмминга}




Поделиться с друзьями:


Дата добавления: 2014-01-06; Просмотров: 333; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.009 сек.