Основы программирования (947332), страница 54
Текст из файла (страница 54)
Создание универсальных объектовДаже отдельные объекты, разработанные для выполнения наиболее часто встречающихся действий, могут существенно упростить программистусоздание программных продуктов. В качестве примера такого «универсального» объекта разработаем класс, объектами которого будут графики функций.Пример 10.2.
Разработать класс, объекты которого представляют собойокно, содержащее график функции одной переменной. Размеры окна, интервал изменения аргумента, его шаг и сама функция должны задаваться основной программой (рис. 10.2).Основные принципы построения графиков функций в программах обсуждались в параграфе 8.6.
По сравнению с программой, рассмотренной там,внесем следующие изменения. Во-первых, обеспечим возможность построения графика функции, заданной в основной программе, для чего используемпараметр процедурного типа. Во-вторых, в процессе разработки методов,обеспечивающих реакции на запросы, выделим внутренние процедуры.В-третьих, координаты точек графика запишем в динамический массив, асам график будем выводить с использованием процедуры рисования ломаной линии DrawPoly.Проектирование класса для реализации объекта начинаем с определенияполей объекта.
Прежде всего, переменные класса должны хранить всю исходную информацию: ссылку на функцию F, интервал изменения аргумента[хп, хк], количество точек п и параметры окнах1, у 1, х2, у2, в которое выводится график. КроСоздать (...)ме того, для построения графика необходимоГрафикзнать минимальное Fmin и максимальные Fmaxзначения функции на заданном отрезке, маештабы т х , т у по осям х и у, шаг изменения арРис. 10.2.
Объект График321Часть 2, Объектно-ориентированное программированиеTWin_grх1,у1,х2,у2, F, xn, xk, n,dx, Fmin, Fmax, mx , my,xm, ym, xs, ys, sInit, Run, Fminmax, Rx, Ryгумента dx, координаты нижней левой точкиграфика XS, ys (они отличаются от координатокна, так как часть окна отводится под выводкоординат сетки) и т. п.Примечание. Целесообразно в скрытых полях переменной-объекта хранить все данные, используемые болеечем в одном методе, за исключением тех, которые в каждом методе инициализируются заново. Последние имеет смысл объявлять локально в каждомметоде.
Например, Fmin, Fmax, xs и ys используются в методах Run, Rx, Ry, поэтому мы храним их в объекте и определяем в инициализирующей процедуре. В то же время динамический массив координат точек используется только в одном методе Run, следовательно, он объявляется в нем локально и там же создается, инициализируется и уничтожается.Рис. 10.3. Класс TWin grКласс должен уметь обрабатывать сообщения Создать и Построить. Соответственно минимально он должен иметь два метода. Назовем их Init(«Инициализировать») и Run («Выполнить»).
Эти методы должны быть доступны из основной программы, а потому объявлены в общедоступной секции public. Разрабатывая алгоритмы этих методов, выделим из метода Initпроцедуру Fminmax, которая будет рассчитывать и инициализировать максимальное и минимальное значения функции на отрезке. Из метода Run выделим в отдельные процедуры последовательности действий по построениюсетки графика Rx - по горизонтали, Ry - по вертикали. Эти методы внутренние, их и все поля класса будем описывать в разделе описаний метода Run,так как доступ к ним из программы не планируется.
Окончательная структура класса TWin_gr показана на рис. 10.3.Ниже приведен текст модуля, содержащего описание класса TWin_gr.Unit WinGr;InterfaceUses crt.Graph;TypeFn =Function(X:real) :real;arr=array[L. 200] ofpointtype;TWin_gr=objectpublicprocedure Inlt(axn,axk:real;an:Integer; aF:Fn;axl,ayl,ax2,ay2:Integer); {инициализация объектов}procedure Run;{вывод графика}privatexl,yl, x2, у2:Integer; {координаты окна}F:Fn;{адрес функции}n:Integer;{количество точек}xn, xk,{интервал изменения аргумента}32210. Классы и объекты в Borland Pascaldx, Fmin, Fmax, {шаг аргумента и экстремумы функции}тх, my:real;{масштабы по осям}хт, ут,{размеры окна}xs,ys:integer;{координаты нижней границы графика}s:string[10];{рабочая строка для вывода разметки}procedure Fminmax; {определение минимума и максимума}procedure Rx;{сетка, параллельная оси ОХ}procedure Ry;{сетка, параллельная оси 0Y}end;Implementation{метод инициализации полей}Procedure TWin_gKlnit;begin{параметры функции}хп:=ахп;xk:=axk;п:=ап;F:=aF:{координаты окна}х1:=ах1;у1:=ау1;х2:=ах2;у2:=ау2;{размер окна}хт:='х2'х1+1;ут:=у2-у1+1;dx:=(xk-xn)/n; {устанавливаем шаг графика функции}Fwmwox; {определяем минимальное и максимальное значенияфункции на заданном отрезке}{определяем нижнюю левую точку графика}xs:=60;ys:=ym'Xs;{определяем масштабы по х и у}mx:=(xm'XS*2J/abs(xk'XnJ ;ту: =(ym'XS *2)/abs(FmaX'Fmin);end;{метод определения экстремумов функции на отрезке}Procedure TWin_gr.
Fminmax;Var X, y:real;i: integer;Beginx:=xn;y:=F(x);323Часть 2. Объектно-ориентированное программированиеFmin:=y;Fmax:-y;for i:=2 ton dobeginx:=x+dx;y:=F(x);if y>Fmax then Fmax:=y;if y<Fmin then Fmin:=y;end;end;{метод построения окна с графиком и координатной сеткой}Procedure JWinjgKRun;Var x:real;i: integer;dinjirr:^arr; {указатель на динамический массив координат точек}BeginSetViewPort(xl,у1 ,x2,y2,true); {устанавливаем окно}ClearViewPort;{очищаем окно}SetColor(2);{устанавливаем цвет рисования}Rectangle(0,0,x2'xJ,y2'yl);{рисуем рамку}SetColor(14);{устанавливаем цвет рисования}SetLineStyle(0,0,3);{устанавливаем стиль линии: толщина 3}х:=хп;GetMem(dinjarr,2*n); {запрашиваем память под массив координат}for i:=J to п dobegindinjarr^fij,x: =round((X'Xn) *mx+xs);dinjarr^fij.y; =round((Fmin'f(x)) ^my+ys);x:'=x+dx;end;DrawPoly(n,dinjarr^);{рисуем график}FreeMemfdinjarrJ'^n); {освобождаем память}SetLineStyle(0,OJ); {устанавливаем стиль линии: толщина 1}Rx;{выводим сетку, параллельную оси х}Ry;{выводим сетку, параллельную оси у}ReadKey; {ожидаем ввода любого символа}end;{метод вывода сетки, параллельной оси х}Procedure TWin^gr.Rx;Var jc, dxl:real;Beginx;=xn;dxl:=(xk'Xn)/5;32410.
Классы и объекты в Borland PascalSetColor(ll);SetTextStyle(0,l,l);repeatStr(x:6:3,s);OutTextXY(round((X'Xn) *mx+xs-3),ys+5,s):Line(round((X'Xn) *mx-^xs),ym'20,round((x-xn) *mx+xs),20);x:=x+dxl;until x>xk+0.0000001;end;{метод вывода сетки, параллельной оси х}Procedure TWin_gr.Ry;Var у, dyl.real;Begin y:=Fmin;SetTextStylefOAl);dyl:=(fmaX'fmin)/5;repeatStr(y:6:3.s);OutTextXY(5, round(- (y-Fmin) "^my+ys-10), s);Line(10, round('(y'Fmin)*my^ys),xm-10, round('(y'Fmin)*my+ys));y:-=y+dyl;until y>Fmax+0.0000001;end;End.Разработав модуль WinGr, мы можем в любой программе построить график. Для этого необходимо: подключить модуль WinGr, описать функцию,объявить соответствующий объект и вызвать методы Init и Run этого объекта.Ниже приведен пример программы, строящей два графика с использованием WinGr.Program Gr;Uses WinGr, Graph;{объявление переменных}VarWl,W2:TWin^_gr;dr, mode: integer;{определение функции}Function f(x:real) :real; far;Beginf: =abs(cos(x *x) *x)End;325Часть 2.
Объектно-ориентированное программирование{основная программа}Begindr:=detect;InitGraphfdnmode, ");WLInit('0.9,0.9,I00fA0,300,400);Wl.Run;W2.Init(l,3,200/,320J00,600,400);W2.Run;EndЗадания для самопроверкиЗадание 1. Спроектируйте универсальный класс для реализации объекта «Круговая диаграмма». Разработайте тестирующую программу.Задание 2. Спроектируйте универсальный класс для реализации объекта «Графическая строка». Предусмотрите возможность изменения цвета символов строки инаправления ее вывода: горизонтальное или вертикальное. Местоположение строкина экране задавайте координатами верхнего левого угла первого символа.
Разработайте тестирующую программу.и . ИЕРАРХИИ КЛАССОВПостроение классов с использованием уже существующих - одно из основных достоинств ООП. Как уже упоминалось выше, в профессиональных средах программирования существуют мощные библиотеки классов, на базе которых строятся классы для решения конкретной задачи. При этом используют средства языка, реализующие основныеотношения между классами: наследование (простое и полиморфное), композицию и наполнение.11.1. НаследованиеНаследованием называют конструирование новых более сложных производных классов из уже имеющихся базовых посредством добавления полей и методов.При наследовании объекты класса-потомка получают возможность использования («наследуют») поля и методы класса-родителя, что позволяетповторно не определять эти компоненты класса.При описании класса-потомка указывают класс-родитель и дополнительные, определенные только для класса-потомка, поля и методы:Туре <имя класса-потомка> = оЬ]ес((<\\мя класса-родителя>)<описание дополнительных полей и методов класса>end;...Пример 11.1.
Разработать класс для реализации объекта Трехмерная комната, который должен реагировать на запрос о площадии объеме комнаты (рис. 11.1).В параграфе 10.3 уже был определенкласс TRoom в модуле Room, который содержал поля для хранения длины и ширины ком-Площадь?Объем?Г—^Трехмернаякомнатак^__ __ JРис. 11.1. ОбъектТрехмерная комната327Часть 2.
Объектно-ориентированное программированиеTRoomlength, widthSquare(), Init'()наты, метод инициализации полей и метод определения площади. Построим класс для реализации объекта Трехмерная комната на базе TRoom, добавив поледля хранения высоты комнаты и метод определенияTVRoomобъема комнаты V, который обращается к методуheightSquare родительского класса (рис. 11.2). КлассV(), NewInitOTRoom также должен включать свой метод инициаРис. 11.2. Иерархия лизации объектов для инициализации нового поляклассов для TVRoom height.Разрабатываемая программа должна содержатьуказание об использовании модуля Room, в котором описан родительскийкласс TRoom:ZProgram ex;Uses Room;Type TVRoom = object(TRoom)heighUreal;{поле для хранения высоты}function V:real;{метод определения объема}procedure Newlnit(lw,h:real); {инициализирующий метод}end;Procedure TVRoom.NewInit;BeginInit(lyW); {инициализируем наследуемые поля класса}height:=h; {инициализируем собственное поле класса}End;Function TVRoom.