TURBO PASCAL |
Новости
|
Использование объектов
Идею инкапсуляции полей и алгоритмов можно применить не только к графическим объектам, но и ко всей программе в целом. Ничто не мешает нам создать объект-программу и «научить» его трем основным действиям: инициации (Init), выполнению основной работы (Run) и завершению (Done). На этапе инициации экран переводится в графический режим работы и создаются и отображаются графические объекты (100 экземпляров TPoint и по одному экземпляру TLine, TCircle, TRecf). На этапе Run осуществляется сканирование клавиатуры и перемещение графических объектов. Наконец, на этапе Done экран переводится в текстовый режим и завершается работа всей программы. Назовем объект-программу именем TGraphApp и разместим его в модуле GraphApp (пока не обращайте внимание на точки, скрывающие содержательную часть модуля -позднее будет представлен его полный текст): Unit GraphApp; Interface type TGraphApp = object Procedure Init; Procedure Run; Destructor Done; end; Implementation Procedure TGraphApp.Init; ... end; ... end. В этом случае основная программа будет предельно простой: Program Graph_0bjects; Uses GraphApp; var App: TGraphApp; begin App.Init; App.Run; App.Done end. В ней мы создаем единственный экземпляр Арр объекта-программы TGrahpApp и обращаемся к трем его методам. Создание экземпляра объекта ничуть не отличается от создания экземпляра переменной любого другого типа. Просто в разделе описания переменных мы указываем имя переменной и ее тип: var Арр: TGraphApp; Получив это указание, компилятор зарезервирует нужный объем памяти для размещения всех полей объекта TGraphApp. Чтобы обратиться к тому или иному объектному методу или полю, используется составное имя, причем первым указывается не имя объектного типа, а имя соответствующей переменной: App.Init; Арр.Run; Арр.Done; Переменные объектного типа могут быть статическими или динамическими, т.е. располагаться в сегменте данных (статические) или в куче (динамические). В последнем случае мы могли бы использовать такую программу: Program Graph_0bjects; Uses GraphApp; type PGraphApp = TGraphApp; var App: PGraphApp; begin App := New(PGraphApp,Init) Арр.Run; Арр.Done end; Для инициации динамической переменной Арр используется вызов функции New. В этом случае первым параметром указывается имя типа инициируемой переменной, а вторым осуществляется вызов метода-конструктора, который, я напомню, нужен для настройки таблицы виртуальных методов. Такой прием (распределение объектов в динамической памяти с одновременной инициацией их ТВМ) характерен для техники ООП. - Ниже приводится возможный вариант модуля GraphApp для нашей учебной программы: Unit GraphApp; Interface Uses GraphObj; const NPoints = 100; {Количество точек} type {Объект-программа} TGraphApp = object Points: array [1..NPoints] of TPoint; {Массив точек} Line: TLine; {Линия} Rect: TRect; {Прямоугольник} Circ: TCircle; {Окружность} ActiveObj : Integer; {Активный объект} Procedure Init; Procedure Run; Procedure Done; Procedure ShowAll; Procedure MoveActiveObj (dX,dY: Integer); end; Implementation Uses Graph, CRT; Procedure TGraphApp.Init; {Инициирует графический режим работы экрана . Создает и отображает NPoints экземпляров объекта TPoint, а также экземпляры объектов TLine, TCircle и TRect} var D,R,Err,k: Integer; begin {Инициируем графику} D := Detect; {Режим автоматического определения типа графического адаптера} InitGraph(D,R, '\tp\bgi') ; {Инициируем графический режим. Текстовая строка должна задавать путь к каталогу с графическими драйверами} Err := GraphResult; {Проверяем успех инициации графики} if Err<>0 then begin GraphErrorMsg (Err) ; Halt end; {Создаем точки} for k : = 1 to NPoints do Points [k] .Init (Random(GetMaxX),Random(GetMaxY),Random(15)+1); {Создаем другие объекты} Line. Init (GetMaxX div 3, GetMaxY div 3,2*GetMaxX div 3, 2*GetMaxY div 3,LightRed); Circ. Init (GetMaxX div 2, GetMaxY div 2, GetMaxY div 5, White); Rect.Init(2*GetMaxX div 5,2*GetMaxY div 5 , 3*GetMaxX div 5, 3*GetMaxY div 5, Yellow); ShowAll; {Показываем все графические объекты} ActiveObj := 1 {Первым перемещаем прямоугольник} end ; { TGraphApp .Init} {-----------} Procedure TGraphApp .Run ; {Выбирает объект с помощью Tab и перемещает его по экрану} var Stop: Boolean; {Признак нажатия Esc} const D = 5; {Шаг смещения фигур} begin Stop := False; {Цикл опроса клавиатуры} repeat case ReadKey of {Читаем код нажатой клавиши} #27: Stop := True; {Нажата Esc} #9:begin {Нажата Tab} inc(ActiveObj); if ActiveObj>3 then ActiveObj := 3 end; #0: case ReadKey of #71:MoveActiveObj(-D,-D); {Влево и вверх} #72:MoveActiveObj( 0,-D); {Вверх} #73:MoveActiveObj( D,-D); {Вправо и вверх} #75:MoveActiveObj(-D, 0); {Влево} #77:MoveActiveObj( D, 0); {Вправо} #79:MoveActiveObj(-D, D); {Влево и вниз} #80:MoveActiveObj( 0, D); {Вниз} #81:MoveActiveObj( D, D); {Вправо и вниз} end end; ShowAll; Until Stop end; {TGraphApp. Run} {-----------} Destructor TGraphApp . Done ; {Закрывает графический режим} begin CloseGraph end; {TGraphApp. Done} Procedure TGraphApp . ShowAll ; {Показывает все графические объекты} var k: Integer; begin for k := 1 to NPoints do Points [k] . Show; Line. Show; Rect . Show; Circ.Show end; {-----------} Procedure TGraphApp.MoveActiveObj; {Перемещает активный графический объект} begin case ActiveObj of 1: Rect.MoveTo(dX,dY); 2: Circ.MoveTo(dX,dY); 3: Line.MoveTo(dX,dY) end end; end. В реализации объекта TGraphApp используется деструктор Done. Следует иметь в виду, что в отличие от конструктора, осуществляющего настройку ТВМ, деструктор не связан с какими-то специфичными действиями: для компилятора слова destructor и procedure - синонимы. Введение в ООП деструкторов носит, в основном, стилистическую направленность - просто процедуру, разрушающую экземпляр объекта, принято называть деструктором. В реальной практике ООП с деструкторами обычно связывают процедуры, которые не только прекращают работу с объектом, но и освобождают выделенную для него динамическую память. И хотя в нашем примере деструктор Done не освобождает кучу, я решил использовать общепринятую стилистику и заодно обсудить с Вами последнее еще не рассмотренное зарезервированное слово технологии ООП. В заключении следует сказать, что формалистика ООП в рамках реализации этой технологии в Турбо Паскале предельно проста и лаконична. Согласитесь, что введение лишь шести зарезервированных слов, из которых действительно необходимыми являются три (object, constructor и virtual), весьма небольшая плата за мощный инструмент создания современного программного обеспечения.
|
(с)Все права защищены По всем интересующим вопросам прошу писать на электронный адрес |