|
Объекты
Воронежский
Государственный Педагогический Университет
Курсовая работа по
информатике на тему:
Объекты
Turbo Pascal 7.0
Выполнил: студент 2-го курса
физико-математического
факультета отделения “физика”
Головачёв Павел Владимирович
Проверил: кандидат техничеких наук,
доцент кафедры
информатики
Кравец Вера
Владимировна
Воронеж 1999.
Оглавление:
1. Объекты (введение).
2. Основные принципы ООП.
3. Постановка учебной задачи.
4. Создание объектов.
5. Использование объектов.
6.
Список
используемой литературы.
Объекты Turbo Pascal 7.0.
1. Объекты.
В основе того или иного
языка программирования лежит некоторая руководящая идея, оказывающая
существенное влияние на стиль соответствующих программ.
Исторически первой была идея
структурирования программ, в соответствии с которой программист должен был
решить, какие именно процедуры он будет использовать в своей программе, а затем
выбрать наилучшие алгоритмы для реализации этих процедур. Появление этой идеи
было следствием недостаточной изученности алгоритмической стороны
вычислительных процессов, стольхарактерной для ранних програмных разработок
(сороковые — пятидесятые годы). Типичным примером процедурно-ориентированного
языка является Фортран – первый и всё ещё один из наиболее популярных языков
программирования. Последовательное использование идеи процедурного
структурирования программ привело к
созданию обширных библиотек программирования, содержащих множество сравнительно
небольших процедур, из которых, как из кирпичиков, можно строить «здание»
программы.
По мере прогресса в области
вычислительной математики акцент в программировании стал смещаться с процедур в
сторону организации данных. Оказалось, что эффективная разработка сложных
программ нуждается в действенных способах контроля правильности использования
данных. Контрольдолжен осуществляться как на стадии компиляции, так и при
прогоне программ, в противном случае, как показала практика, резко возрастают
трудности создания крупных програмных проектов. Отчётливое осознание этой
проблемы привело к созданию Ангола-60, а позже Паскаля, Модулы-2, Си и
множества других языков программирования, имеющих более или менее развитые
структуры типов данных. Логическим следствием развития этого направления стал
модульный подход к разработке программ, характеризующийся стремлением
«спрятать» данные и процедуры внутри модуля.
Начиная с языка Симула-67, в
программировании наметился новый подход, который получил название объектно-ориентированного программирования
(в дальнейшем ООП). Его руководящая идея заключается в стремлении связать
данные с обрабатывающими эти данные процедурами в единое целое – объект. Характерной чертой объектов
является инкапсуляция (объединение)
данных и алгоритмов их обработки, в результате чего и данные, и процедуры во
многом теряют самостоятельное значение. Фактически ООП можно рассматривать как
модульное программирование ноаого уровня, когда вместо во многом случайного,
механического объединения процедур и данных акцент делается на их смысловую
связь.
Какими мощными средствами
располагает ООП наглядно демонстрирует библиотека Turbo Vision, входящая в комплект поставки Турбо Паскаля. В этой
работе рассмотрены основные идеи ООП и способы их использования.
Следует заметить, что
преимущества ООП в полной мере проявляются лишь при разработке достаточно
сложных программ. Более того, инкапсуляция придаёт объектам совершенно новое
свойство «самостоятельности», максимальной независимости от остальных частей
программы. Правильно сконструированный объект располагает всеми необходимыми
данными и процедурами их обработки, чтобы успешно реализовать тербуемые от него
действия. Попытки использовать ООП для
программирования несложных алгоритмов, связанных, например, с рассчётными
вычислениями по готовым формулам, чаще всего выглядят искуственными
нагромождениями ненужных языковых конструкций. Такие программы обычно не
нуждаются в структуризации, расчленении алгоритма на ряд относительно
независимых частей, их проще и естественнее разрабатывать традиционными
способами Паскаля. При разработке сложных диалоговых программ программист
вынужден структурировать программу, так как только в этом случае он может
рассчитывать на успех: «критической массой» неструктурированных программ
является объём в 1000-1200 строк исходного текста – отладка неструктурированных
программ болшего объёма обычно сталкивается с чрезмерными трудностями.
Структурирование программы ведёт, фактически, к разработке собственной
библиотеки программирования – вот в этот момент на помощь приходят новые
средства ООП.
2. Основные принципы ООП.
Объектно-ориентированное программирование
основано на «трёх китах» – трёх важнейших принципах, придающих объектам новые
свойства. Этими принципами являются инкапсуляция, наследование и полиморфизм.
Инкапсуляция есть объединение в единое целое данных и алгоритмов обработки этих
данных. В рамках ООП данные называются полями
объекта, а алгоритмы – объектными методами.
Инкапсуляция позволяет в
максимальной степени изолировать объект от внешнего окружения. Она существенно
повышает надёжность разрабатываемых программ, т.к. локализованные в объекте
алгоритмы обмениваются с программой сравнительно небольшими объёмами данных,
причём количество и тип этих данных обычно тщательно контролирутся. В
результате замена или модификация алгоритмов и данных, инкапсулированных в
объект, как правило, не влечёт за собой плохо прослеживаемых последствий для
программы в целом (в целях повышения защищённости прграмм в ООП почти не
используются глобальные переменные).
Другим немаловажным
следствием инкапсуляции является лёгкость обмена объектами, переноса их из
одной программы в другую. Можно сказать, что ООП «провоцирует» разработку
библиотек объектов, таких как Turbo
Vision.
Наследование есть свойство объектов порождать своих потомков. Объект-потомок автоматически
наследует от родителя все поля и методы, может дополнять объекты новыми полями
и заменять (перекрывать) методы родителя или дополнять их.
Принцип наследования решает
проблему модификации свойств объекта и придаёт ООП в целом исключительную
гибкость. При работе с объектами программист обычно подбирает объект, наиболее
близкий по своим свойствам для решения конкретной задачи, и создаёт одного или
нескольких потомков от него, которые «умеют» делать то, что не реализовано в
родителе.
Последовательное проведение
в жизнь принципа «наследуй и изменяй» хорошо согласуется с поэтапным подходом к
разработке крупных програмных проектов и во многом стимулирует такой подход.
Полиморфизм – это свойство родственных объектов (т.е. объектов, имеющих одного
общего родителя) решать схожие по смыслу проблемы разными способами. В рамках
ООП поведенческие свойства объекта определяются набором вхожящих в него
методов. Изменяя алгоритм того или иного метода в потомках объекта, программист
может придавать этим потомкам отсутствующие у родителя специфические свойства.
Для изменения метода необходимо перекрыть
его в потомке, т.е. объявить в потомке одноимённый метод и реализовать в нём
нужные действия. В результате в объекте-родителе и объекте-потомке будут
действовать два одноимённых метода,
имеющие разную алгоритмическую основу и, следовательно, придающие объектам
разные свойства. Это и называется полиморфизмом объектов.
В Турбо Паскале полиморфизм
достигается не только описанным выше механизмом наследования и перекрытия
методов родителя, но и их виртуализацией
(см. ниже), позволяющей родительским методам обращаться к методам потомков.
3. Постановка учебной задачи.
Знакомство с техникой ООП в
этой работе иллюстрируется примерами, объединёнными рамками следующей учебной
задачи.
Требуется разработать
программу, которая создаёт на экране ряд графических изображений (точки,
окружность, линия, квадрат) и может перемещать эти изображения по экрану. Вид
создаваемого программой экрана показан ниже.
Для перемещения изображений в программе будут использоваться
клавиши управления курсором, клавиши Home,
End, PgUr, PgDn (для пермещения по
диагональным направлениям) и клавиша Tab для выбора перемещаемого объекта. Выход из
программы – клавиша Esc.
Техническая реализация
программы потребует использования средств двух стандартных библиотек – CRT
и GRAPH. Чтобы не отвлекать внимание от основных проблем ООП, при описании
реализации учебной задачи особенности использования средств этих библиотек лишб
очень кратко коментируются в текстах программы.
4. Создание объектов.
В Турбо Паскале для создания
объектов используется три зарезервированных слова: object, constructor, destructor и три стандартные
директивы: private, public
и virtual.
Зарезервированное слово object используется для описания объекта. Описание объекта
должно помещаться в разделе описания типов:
type
MyObject
= object
{поля объекта}
{методы объекта}
end;
Если объект порождается от
какого-либо родителя, имя родителя указывается в круглых скобках сразу за
словом object:
type
MyDescendantObject = object
(MyObject)
............................................................
............................................................
end;
Любой объект может иметь
сколько угодно потомков, но только одного родителя, что позволяет создавать
иерархические деревья наследования объектов.
Для данной учебной задачи
создадим объект-родитель TGraphObject, в рамках которого инкапсулированы поля и методы,
общие для всех остальных объектов:
type
TGraphObj
= object
Private
{поля объекта будут скрыты
от пользователя}
X,Y: Integer; {координаты
реперной точки}
Color: Word; {цвет фигуры}
Public
Constructor Init (aX, aY: Integer; aColor: Word);
{создаёт
экзепляр объекта}
Procedure Draw (aColor: Word); Virtual;
{вычерчивает объект заданным
цветом aColor}
Procedure Show;
{показывает
объект – вычерчивает его цветом Color}
Procedure Hide;
{прячет объект – вычерчивает
его цветом фона}
Procedure MoveTo (dX, dY: Integer);
{перемещает
объект в точку с координатами X+dX и
Y+dY}
end; {конец описания объекта TGraphObj}
Â
äàëüíåéøåì
ïðåäïîëàãàåòñÿ
ñîçäàòü îáúåêòû-ïîòîìêè
îò TGraphObject,
ðåàëèçóþùèå
âñå
ñïåöèôè÷åñêèå
ñâîéñòâà
òî÷êè, ëèíèè,
îêðóæíîñòè
è
ïðÿìîóãîëüíèêà.
Êàæäûé èç
ýòèõ ãðàôè÷åñêèõ
îáúåêòîâ
áóäåò
õàðàêòåðèçîâàòüñÿ
ïîëîæåíèåì
íà ýêðàíå
(ïîëÿ X è
Y) è
öâåòîì (ïîëå Color). Ñ
ïîìîùüþ
ìåòîäà Draw îí áóäåò
ñïîñîáåí
îòîáðàæàòü
ñåáÿ íà ýêðàíå,
à ñ ïîìîùüþ
ñâîéñòâ
ïîêàçàòü
ñåáÿ” (ìåòîä Show) è
ñïðÿòàòü
ñåáÿ” (ìåòîä Hide)
ñìîæåò
ïåðåìåùàòüñÿ
ïî ýêðàíó
(ìåòîä MoveTo).
Ó÷èòûâàÿ
îáùíîñòü
ñâîéñòâ
ãðàôè÷åñêèõ
îáúåêòîâ, ìû
îáúÿâëÿåì
àáñòðàêòíûé
îáúåêò TGraphObj, êîòîðûé
íå ñâÿçàí ñ
êîíêðåòíîé
ãðàôè÷åñêîé
ôèãóðîé. Îí
îáúåäèíÿåò
â ñåáå âñå îáùèå
ïîëÿ è ìåòîäû
ðåàëüíûõ
ôèãóð è
áóäåò
ñëóæèòü ðîäèòåëåì
äëÿ äðóãèõ
îáúåêòîâ.
Äèðåêòèâà Private
â îïèñàíèè
îáúåêòà
îòêðûâàåò
ñåêöèþ îïèñàíèÿ
ñêðûòûõ
ïîëåé è
ìåòîäîâ.
Ïåðå÷èñëåííûå
â ýòîé
ñåêöèè
ýëåìåíòû
îáúåêòà “íå âèäíû”
ïðîãðàììèñòó,
åñëè ýòîò
îáúåêò îí ïîëó÷èë
â ðàìêàõ
áèáëèîòå÷íîãî
TPU-ìîäóëÿ.
Ñêðûâàþòñÿ
îáû÷íî òå
ïîëÿ è ìåòîäû,
ê êîòîðûì
ïðîãðàììèñò
(â åãî æå
èíòåðåñàõ!)
íå äîëæåí
èìåòü
íåïîñðåäñòâåííîãî
äîñòóïà. Â
äàííîì
ïðèìåðå îí íå
ìîæåò
ïðîèçâîëüíî
ìåíÿòü
êîîðäèíàòû
ðåïåðíîé
òî÷êè (X,Y),
ò.ê. ýòî íå
ïðèâåä¸ò ê
ïåðåìåùåíèþ
îáúåêòà. Äëÿ
èçìåíåíèÿ
ïîëåé X
è Y
ïðåäóñìîòðåíû
âõîäÿùèå â
ñîñòàâ
îáúåêòà
ìåòîäû
Init è MoveTo. Ñêðûòûå
ïîëÿ è ìåòîäû
äîñòóïíû â
ðàìêàõ òîé
ïðîãðàììíîé
åäèíèöû
(ïðîãðàììû
èëè ìîäóëÿ),
ãäå îïèñàí
ñîîòâåòñòâóþùèé
îáúåêò. Â
äàëüíåéøåì
ïðåäïîëàãàåòñÿ,
÷òî ïðîãðàììà
áóäåò
èñïîëüçîâàòü
ìîäóëü GraphObj
ñ îïèñàíèåì
îáúåêòîâ.
Ñêðûòûå ïîëÿ
áóäóò
äîñòóïíû â
ìîäóëå GraphObj,
íî
íåäîñòóïíû
â
èñïîëüçóþùåé
åãî îñíîâíîé
ïðîãðàììå.
Ðàçóìååòñÿ,
â ðàìêàõ
ðåàëüíîé
çàäà÷è
ñîçäàíèå
ñêðûòûõ
ýëåìåíòîâ îáúåêòà
âîâñå
íåîáÿçàòåëüíî.
 îáúåêò TGraphObj îíè
ââåäåíû ëèøü
äëÿ
èëëþñòðàöèè
âîçìîæíîñòåé
ÎÎÏ.
Äèðåêòèâà public
îòìåíÿåò
äåéñòâèå
äèðåêòèâû private,
ïî ýòîìó âñå
ñëåäóþùèå
çà public
ýëåìåíòû
îáúåêòà
äîñòóïíû â
ëþáîé
ïðîãðàììíîé
åäåíèöå.
Äèðåêòèâû private
è public ìîãóò
ïðîèçâîëüíûì
îáðàçîì
÷åðåäîâàòüñÿ
â ïåðäåëàõ
îäíîãî
îáúåêòà.
Âàðèàíòû
îáúÿâëåíèÿ
îáúåêòà TGraphObj áåç
èñïîëüçîâàíèÿ
ìåõàíèçìà private...public:
type
TGraphObj = object
X,Y: Integer;
Color: Word;
Constructor Init (aX,aY: Integer; aColor: Word);
Procedure Draw (aColor:
Word); Virtual;
Procedure Show;
Procedure Hide;
Procedure MoveTo (dX,dY:
Integer);
end;
Îïèñàíèÿ
ïîëåé íè÷åì
íå
îòëè÷àþòñÿ
îò îïèñàíèÿ
îáû÷íûõ
ïåðåìåííûõ.
Ïîëÿìè ìîãóò
áûòü ëþáûå
ñòðóêòóðû
äàííûõ, â òîì
÷èñëå è
äðóãèå
îáúåêòû.
Èñïîëüçóåìûå
â äàííîì
ïðèìåðå ïîëÿ X è Y ñîäåðæàò
êîîðäèíàòó
ðåïåðíîé
(õàðàêòåðíîé)
òî÷êè
íðàôè÷åñêîãî
îáúåêòà, à
ïîëå Color —
åãî öâåò.
Ðåïåðíàÿ
òî÷êà
õàðàêòåðèçóåò
òåêóùåå
ïîëîæåíèå
ãðàôè÷åñêîé
ôèãóðû íà ýêðàíå
è, â ïðèíöèïå,
ìîæåò áûòü
ëþáîé å¸
òî÷êîé (â
äàííîì
ïðèìåðå îíà
ñîâïàäàåò ñ
êîîðäèíàòàìè
òî÷êè â
îïèñûâàåìîì
íèæå
îáúåêòå TPoint, ñ öåíòðîì
îêðóæíîñòè
â îáúåêòå TÑircle,
ïåðâûì
êîíöîì
ïðÿìîé â
îáúåêòå TLine è ñ ëåâûì
âåðõíèì
óãëîì
ïðÿìîóãîëüíèêà
â îáúåêòå TRect).
Äëÿ
îïèñàíèÿ
ìåòîäîâ â ÎÎÏ
èñïîëüçóþòñÿ
òðàäèöèîííûå
äëÿ Ïàñêàëÿ
ïðîöåäóðû è
ôóíêöèè, à
òàê æå
îñîáûé âèä
ïðîöåäóð — êîíñòðóêòîðû
è äåñòðóêòîðû.
Êîíñòðóêòîðû
ïðåäíàçíà÷åíû
äëÿ ñîçäàíèÿ
êîíêðåòíîãî
ýêçåìïëÿðà
îáúåêòà,
âåäü îáúåêò —
ýòî òèï
äàííûõ, ò.å.
øàáëîí”, ïî
êîòîðîìó
ìîæíî
ñîçäàòü ñêîëüêî
óãîäíî
ðàáî÷èõ
ýêçåìïëÿðîâ
äàííûõ îáúåêòíîãî
òèïà (òèïà TGraphObj,
íàïðèìåð).
Çàðåçåðâèðîâàííîå
ñëîâî constructor,
èñïîëüçóåìîå
â çàãîëîâêå
êîíñòðóêòîðà
âìåñòî
procedure,
ïðåäïèñûâàåò
êîìïèëÿòîðó
ñîçäàòü
îñîáûé êîä
ïðîëîãà, ñ
ïîìîùüþ
êîòîðîãî
íàñòðàèâàåòñÿ
òàê
íàçûâàåìàÿ
òàáëèöà
âèðòóàëüíûõ
ìåòîäîâ (ñì.
íèæå). Åñëè â
îáúåêòå íåò
âèðòóàëüíûõ
ìåòîäîâ, â
í¸ì ìîæåò íå
áûòü íè
îäíîãî
êîíñòðóêòîðà,
íàîáîðîò,
åñëè õîòÿ áû
îäèí ìåòîä
îïèñàí êàê
âèðòóàëüíûé
(ñ ïîñëåäóþùèì
ñëîâîì Virtual, ñì
ìåòîä Draw),
â ñîñòàâ
îáúåêòà äîëæåí
âõîäèòü
õîòÿ áû îäèí
êîíñòðóêòîð
è îáðàùåíèå
ê
êîíñòðóêòîðó
äîëæíî
ïðåæøåñòâîâàòü
îáðàùåíèþ ê
ëþáîìó
âèðòóàëüíîìó
ìåòîäó.
Òèïè÷íîå
äåéñòâèå,
ðåàëèçóåìîå
êîíñòðóêòîðîì,
ñîñòîèò â
íàïîëíåèè
îáúåêòíûõ ïîëåé
êîíêðåòíûìè
çíà÷åíèÿìè.
Ñëåäóåò çàìåòèòü,
÷òî ðàçíûå
ýêçåìïëÿðû
îäíîãî è òîãî
æå îáúåêòà
îòëè÷àþòñÿ
äðóã îò äðóãà
òîëüêî
ñîäåðæèìûì
îáúåêòíûõ
ïîëåé, â òî àðåìÿ
êàê êàæäûé
èç íèõ
èñïîëüçóåò
îäíè è òå æå
îáúåêòíûå
ìåòîäû. Â
äàííîì
ïðèìåðå êîíñòðóêòîð Init
îáúåêòà TGraphObj
ïîëó÷àåò
âñå
íåîáõîäèìûå
äëÿ ïîëíîãî
îïðåäåëåíèÿ
ýêçåìïëÿðà
äàííûå
÷åðåç ïàðàìåòðû
îáðàùåíèÿ aX, aY, aColor.
Ïðîöåäóðà Draw
ïðåäíàçíà÷åíà
äëÿ
âû÷åð÷èâàíèÿ
ãðàôè÷åñêîãî
îáúåêòà. Ýòà
ïðîöåäóðà
áóäåò ðåàëèçîâûâàòüñÿ
â ïîòîìêàõ
îáúåêòà TGraphObj
ïî-ðàçíîìó.
Íàïðèìåð, äëÿ
âèçóàëèçàöèè
òî÷êè
ñëåäóåò
âûçâàòü
ïðîöåäóðó PutPixel, äëÿ
âû÷åð÷èâàíèÿ
ëèíèè —
ïðîöåäóðó Line è ò.ä. Â
îáúåêòå TGraphObj
ïðîöåäóðà Draw
îïðåäåëåíà
êàê âèðòóàëüíàÿ
(“âîîáðàæàåìàÿ”).
Àáñòðàêòíûé
îáúåêò TGraphObj íå ïðåäíàçíà÷åí
äëÿ âûâîäà íà
ýêðàí,
îäíàêî íàëè÷èå
ïðîöåäóðû Draw â ýòîì
îáúåêòå
ãîâîðèò î
òîì, ÷òî
ëþáîé ïîòîìîê
TGraphObj
äîëæåí èìåòü
ñîáñòâåííûé
ìåòîä Draw,
ñ ïîìîùüþ
êîòîðîãî îí
ìîæåò
ïîêàçàòü
ñåáÿ íà
ýêðàíå.
Ïðè
òðàíñëÿöèè
îáúåêòà,
ñîäåðæàùåãî
âèðòóàëüíûå
ìåòîäû,
ñîçäà¸òñÿ
òàê
íàçûâàåìàÿ òàáëèöà
âèðòóàëüíûõ
ìåòîäîâ
(ÒÂÌ),
êîëè÷åñòâî
ýëåìåíòîâ
êîòîðîé
ðàâíî
êîëè÷åñòâó
âèðòóàëüíûõ
ìåòîäîâ
îáúåêòà. Â
ýòîé
òàáëèöå
áóäóò
õðàíèòüñÿ
àäðåñà òî÷åê
âõîäà â
êàæäûé
âèðòóàëüíûé
ìåòîä. Â äàííîì
ïðèìåðå ÒÂÌ
îáúåêòà TGraphObj õðàíèò
åäèíñòâåííûé
ýëåìåíò —
àäðåñ ìåòîäà
Draw.
Ïåðâîíà÷àëüíî
ýëåìåíòû
ÒÂÌ íå
ñîäåðæàò êîíêðåòíûõ
àäðåñîâ. Åñëè
áû ìû
ñîçäàëè ýêçåìïëÿð
îáúåêòà TGraphObj ñ
ïîìîùüþ
âûçîâà åãî
êîíñòðóêòîðà
Init, êîä
ïðîëîãà
êîíñòðóêòîðà
ïîìåñòèë áû
â ÒÂÌ íóæíûé
àäðåñ
ðîäèòåëüñêîãî
ìåòîäà Draw. Äàëåå ìû
ñîçäàäèì
íåñêîëüêî
ïîòîìêîâ îáúåêòà
TGraphObj.
Êàæäûé èç
íèõ áóäåò
èìåòü
ñîáñòâåííûé
êîíñòðóêòîð,
ñ ïîìîùüþ
êîòîðîãî
ÒÂÌ êàæäîãî
ïîòîìêà
íàñòðàèâàåòñÿ
òàê, ÷òîáû å¸ åäèíñòâåííûé
ýëåìåíò
ñîäåðæàë
àäðåñ íóæíîãî
ìåòîäà Draw. Òàêàÿ
ïðîöåäóðà
íàçûâàåòñÿ ïîçäíèì
ñâÿçûâàíèåì
îáúåêòà.
Ïîçäíåå
ñâÿçûâàíèå
ïîçâîëÿåò ìåòîäÿì
ðîäèòåëÿ
îáðàùàòüñÿ
ê âèðòóàëüíûì
ìåòîäàì
ñâîèõ
ïîòîìêîâ è
èñïîëüçîâàòü
èõ äëÿ
ðåàëèçàöèè
ñïåöèôè÷íûõ
äëÿ ïîòîìêîâ
äåéñòâèé.
Íàëè÷èå â
îáúåêòå TGraphObj
âèðòóàëüíîãî
ìåòîäà Draw ïîçâîëÿåò
ëåãêî
ðåàëèçîâàòü
òðè äðóãèõ ìåòîäà
îáúåêòà:
÷òîáû
ïîêàçàòü
îáúåêò íà ýêðàíå
â ìåòîäå Show,
âûçûâàåòñÿ Draw ñ
öâåòîì aColor,
ðàâíûì
çíà÷åíèþ
ïîëÿ Color,
à ÷òîáû
ñïðÿòàòü
ãðàôè÷åñêèé
îáúåêò, â ìåòîäå
Hide
âûçûâàåòñÿ Draw ñî
çíà÷åíèåì
öâåòà GetBkColor,
ò.å. ñ
òåêóùèì
öâåòîì ôîíà.
Ðàññìîòðèì
ðåàëèçàöèþ
ïåðåìåùåíèÿ
îáúåêòà.
Åñëè
ïîòîìîê TGraphObj (íàïðèìåð, TLine)
õî÷åò
ïåðåìåñòèòü
ñåáÿ íà
ýêðàíå, îí
îáðàùàåòñÿ
ê
ðîäèòåëüñêîìó
ìåòîäó
MoveTo. Â ýòîì
ìåòîäå
ñíà÷àëà ñ
ïîìîùüþ Hide îáúåêò
ñòèðàåòñÿ ñ
ýêðàíà, à
çàòåì ñ ïîìîùüþ
Show
ïîêàçûâàåòÿ
â äðóãîì
ìåñòå. Äëÿ
ðåàëèçàöèè
ñâîèõ
äåéñòâèé è Hide, è Show îáðàùàþòñÿ
ê
âèðòóàëüíîìó
ìåòîäó Draw.
Ïîñêîëüêó
âûçîâ MoveTo
ïðîèñõîäèò â
ðàìêàõ
îáúåêòà TLine,
èñïîëüçóåòñÿ
ÒÂÌ ýòîãî
îáúåêòà è
âûçûâàåòñÿ
åãî ìåòîä Draw,
âû÷åð÷èâàþùèé
ïðÿìóþ. Åñëè
áû ïåðåìåùàëàñü
îêðóæíîñòü,
ÒÂÌ
ñîäåðæàëà áû
àäðåñ ìåòîäà
Draw îáúåêòà TÑircle
è
âèçóàëèçàöèÿ-ñòèðàíèå
îáúåêòà
îñóùåñòâëÿëàñü
áû ñ ïîìîùüþ ýòîãî
ìåòîäà.
×òîáû
îïèñàòü âñå
ñâîéñòâà
îáúåêòà, íåîáõîäèìî
ðàñêðûòü
ñîäåðæèìîå
îáúåêòíûõ ìåòîäîâ,
ò.å. îïèñàòü
ñîîòâåòñòâóþùèå
ïðîöåäóðû è
ôóíêóèè.
Îïèñàíèå
ìåòîäîâ
ïðîèçâîäèòñÿ
îáû÷íûì äëÿ
Ïàñêàëÿ
ñïîñîáîì â ëþáîì
ìåñòå
ðàçäåëà
îïèñàíèé, íî
ïîñëå îïèñàíèÿ
îáúåêòà.
Íàïðèìåð:
type
TGraphObj = object
.................................
.................................
end;
Constructor TGraphObj.Init;
begin
X:= aX;
Y:= aY;
Color:= aColor
end;
Procedure TGraphObj.Draw;
begin
{Ýòà
ïðîöåäóðà â
ðîäèòåëüñêîì
îáúåêòå íè÷åãî
íå äåëàåò,
ïîýòîìó
ýêçåìïëÿëðû
TGraphObj íå ñïîñîáíû
îòîáðàæàòü
ñåáÿ íà
ýêðàíå.
×òîáû ïîòîìêè
îáúåêòà TGraphObj
áûëè
ñïîñîáíû
îòîáðàæàòü
ñåáÿ, îíè
äîëæíû
ïåðåêðûâàòü
ýòîò ìåòîä}
end;
Procedure TGraphObj.Show;
begin
Draw (Color)
end;
Procedure TGraphObj.Hide;
begin
Draw (GetBkColor)
end;
Procedure TGraphObj.MoveTo;
begin
Hide;
X:= X+dX;
Y:= Y+dY;
end;
Îòìå÷ó äâà
îáñòîÿòåëüñòâà.
Âî-ïåðâûõ, ïðè îïèñàíèè
ìåòîäîâ èìÿ
ìåòîäà
äîïîëíÿåòñÿ
ñïåðåäè
èìåíåì
îáúåêòà, ò.å.
èñïîëüçóåòñÿ
ñîñòàâíîå
èìÿ ìåòîäà.
Ýòî
íåîáõîäèìî
ïî òîé ïðîñòîé
ïðè÷èíå, ÷òî
â èåðàðõèè
ðîäñòâåííûõ
îáúåêòîâ
ëþáîé èç
ìåòîäîâ
ìîæåò áûòü
ïåðåêðûò â
ïîòîìêàõ.
Ñîñòàâíûå
èìåíà ÷¸òêî
óêàçûâàþò
ïðèíàäëåæíîñòü
êîíêðåòíîé
ïðîöåäóðû.
Âî-âòîðûõ, â
ëþáîì
îáúåêòíîì
ìåòîäå ìîæíî
èñïîëüçîâàòü
èíêàïñóëèðîâàííûå
ïîëÿ îáúåêòà
ïî÷òè òàê,
êàê åëè áû
îíè áûëè îïðåäåëåíû
â êà÷åñòâå
ãëîáàëüíûõ
ïåðåìåííûõ.
Íàïðèìåð, â
êîíñòðóêòîðå
TGraph.Init
ïåðåìåííûå â
ëåâûõ
÷àñòÿõ
îïåðàòîðîâ
ïðèñâàèâàíèÿ
ïðåäñòàâëÿþò
ñîáîé
îáúåêòíûå
ïîëÿ è íå
äîëæíû
çàíîâî
îïèñûâàòüñÿ
â ïðîöåäóðå.
Áîëåå òîêî,
îïèñàíèå
Constructor TGraph.Init;
var
X,Y: Integer; {îøèáêà!}
Color: Word; {îøèáêà!}
begin
..........................
..........................
end;
âûçîâåò
ñîîáùåíèå î
äâîéíîì
îïðåäåëåíèè
ïåðåìåííûõ X, Y, Color (â
ýòîì è
ñîñòîèò
îòëè÷èå â
èñïîëüçîâàíèè
ïîëåé îò
ãëîáàëüíûõ
ïåðåìåííûõ:
ãëîáàëüíûå
ïåðåìåííûå
ìîæíî
ïåðåîïðåäåëÿòü
â ïðîöåäóðàõ,
â òî âðåìÿ
êàê îáúåêòíûå
ïîëÿ
ïåðåîïðåäåëÿòü
íåëüçÿ).
Ñòîèò
îáðàòèòü
âíèìàíèå íà
òî, ÷òî àáñòðàêòíûé
îáúåêò TGraphObj íå
ïðåäíàçíà÷åí
äëÿ âûâîäÿ íà
ýêðàí, ïîýòîìó
åãî ìåòîä Draw
íè÷åãî íå
äåëàåò.
Îäíàêî
ìåòîäû Hide,
Show, MoveTo “çíàþò”
ôîðìàò
âûçîâà
ýòîãî
ìåòîäà è
ðåàëèçóþò
íåîáõîäèìûå
äåéñòâèÿ,
îáðàùàÿñü ê
ðåàëüíûì
ìåòîäàì Draw ñâîèõ
áóäóùèõ
ïîòîìêîâ
÷åòåç
ñîîòâåòñòâóþùèå
ÒÂÌ. Ýòî è
åñòü
ïîëòìîðôèçì
îáúåêòîâ.
Ñîçäàäèì
ïðîñòåéøåãî
ïîòîìêà îò Tgraphobj —
îáúåêò TÐoint, ñ
ïîìîùüþ
êîòîðîãî
áóäåò
âèçóàëèçèðîâàòüñÿ
è
ïåðåìåùàòüñÿ
òî÷êà. Âñå
îñíîâíûå äåéñòâèÿ,
íåîáõîäèìûå
äëÿ ýòîãî,
óæå åñòü â
îáúåêòå TGraphObj, ïîýòîìó
â îáúåêòå TPoint
ïåðåêðûâàåòñÿ
åäèíñòâåííûé
ìåòîä — Draw:
type
TPoint = object (TGraphObj)
Procedure Draw (aColor); Virtual;
end;
Procedure TPoint.Draw;
begin
PutPixel (X,Y,Color)
{ïîêàçûâàåì
öâåòîì Color
ïèêñåëü ñ
êîîðäèíàòàìè
X è Y}
end;
В новом объекте TРoint можно использовать любые методы
объекта-родителя TGraphObj. Например,
вызвать метод MoveTo, чтобы
переместить изображение точки на новое место. В этом случае родительский метод TGraphObj.MoveTo будет обращаться к
методу TPoint.Draw, чтобы спрятать и
затем показать изображение точки. Такой вызов станет доступен после обращения к
конструктору Init объекта TРoint, который нужным образом настроит
ТВМ объекта. Если вызвать TPoint.Draw
до вызова Init, его ТВМ не будет
содержать правильного адреса и программа “зависнет”.
Чтобы создат объект-линию,
необходимо ввести два новых поля для хранения координат другого конца.
Дополнительные поля требуется наполнить конкретными значениями, поэтому нужно
перекрыть конструктор родотельского объекта:
type
TLine = object
(TGraphObj)
dX, dY: Integer; {Приращение координат второго конца}
Constructor
Init (X1, Y1, X2, Y2: Integer; aColor: Word); Virtual;
end;
Constructor TLine.Init;
{Вызывает унаследованный конструктор TGraphObj для инициации полей
X, Y, Color. Затем инициирует поля dX, dY}
begin
{Вызываем
унаследованный конструктор}
Inherited Init (X1, Y1, aColor);
{Инициируем поля dX,
dY}
dX:= X2-X1;
dY:= Y2-Y1
end;
Procedure Draw;
begin
SetColor (Color); {Устанавливаем цвет Color}
Line (X, Y, X+dX, Y+dY) {Вычерчиваем линию}
end;
В конструкторе TLine.Init для инициации полей X, Y, Color, унаследованных от
родмтельского объекта, вызывается унаследованный конструктор TGraph.Init, для чего используется
зарезервированное слово inherited (англ. — унаследованный):
Inherited Init (X1, Y1, aColor);
C таким же успехом мы могли бы использовать и
составное имя метода:
TGraphObj.Init (X1, Y1,
aColor);
Для инициации полей dX и dY
вычисляется расстояние в пикселах по горизонтали и вертикали от первого конца
прямой до её второго конца. Это позволяет в методе TLine.Draw вычислить координаты второго конца по координатам
первого и смещениям dX, dY. В
результате простое изменение координат реперной точки X,Y в родительском методе TGraph.MoveTo
перемещает всю фигуру по экрану.
Теперь нетрудно реализовать
объект TСircle для создания и
перемещения окружности:
type
TCircle = object
(TGraphObj)
R: Integer;
Constructor
Init (aX, aY, aR: Integer; aColor: Word);
Procedure Draw (aColor: Virtual);
end;
Constructor TCircle.Init;
begin
Inherited Init
(aX, aY, aColor);
R:= aR
end;
Procedure TCircle.Draw;
begin
SetColor (aColor); {устанавливает
цвет Color}
Circle (X, Y, R) {вычерчивает
окружность}
end;
В объекте Trect, с помощью которого создаётся и
перемещается прямоугольник, учтём то обстоятельство, что для задания прямоугольника
требуется указать четыре целочисленных параметря, т.е. столько же, сколько для
задания линии. Поэтому объект TRect
удобнее породить не от TGraphObj, а
от TLine, чтобы использовать его конструктор Init:
tipe
TRect = object
(TLine)
Procedure Draw (aColor: Word);
end;
Procedure TRect.Draw;
begin
SetColor (aColor);
Rectangle (X, Y, X+dX, Y+dY) {вычерчиваем
прямоугольник}
end;
Чтобы описания графических
объектов не мешали созданию основной программы, оформим эти описания в
отдельном модуле GraphObj:
Unit
GraphObj;
Interface
{интерфейсная часть модуля содержит только объявления объектов}
type
TGraphObj = object
.................................
.................................
end;
TPoint = object
(TGraphObj)
................................................
................................................
end;
TLine = object
(TGraphObj)
..............................................
..............................................
end;
TCircle = object
(TGraphObj)
...............................................
...............................................
end;
TRect = object
(Tline)
...................................
...................................
end;
Implementation
{исполняемая часть содержит описания всех объектных методов}
Uses
Graph;
Constructor TGraphObj.Init;
..............................................
..............................................
end.
В интерфейсной части модуля
приводятся лишь объявления объектов, подобно тому как описываются другие типы
данных, объявляемые в модуле доступными для внешних программных едениц.
Расшифровка объектных методов помещается в исполняемую часть implementation, как если бы это были
описания обычных интерфейсных процедур и функций. При описании методов можно
опускать повторное описание в заголовке параметров вызова. Если они всё же
повторяются, они должны в точности соответствовать ранее объявляемым параметрам
в описании объекта. Например, заголовок конструктора TGraphObj.Init может быть таким:
Сonstructor TGraphObj.Init;
или таким:
Сonstructor TGraphObj.Init (aX, aY: Integer; aColor: Word);
5. Использование Объектов.
Идею инкапсуляции полей и
алгоритмов можно применить не только к графическим объектам, но и ко всей
прграмме в целом. Ничто не мешает нам создать объект-программу и “научить” его
трём основным действиям: инициации (Init),
выполнению основной работы (Run),
завершению (Done). На этапе инициации
экран переволится в графический режим работы и создаются и отображаются
графические объекты (100 экземпляров TРoint
и по одному экземпляру TLine, TCircle,
TRect). На этапе Run
осуществляется сканирование клавиатуры и перемещение графических объектов.
Наконец, на этапе Done экран
переводится в текстовый режим и завершается работа всей программы.
Назовём объект-программу
именем TGraphApp и разместим его в
модуле GraphApp (пока не обращайте
внимания на точки, скрывающие содержательную часть модуля — позднее будет
представлен его полный текст):
Unit
GraphApp;
Intrface
type
TGraphApp = object
Procedure Init;
Procedure Run;
Destructor Done;
end;
Implementation
Procedure TGraphApp.Init;
............................................
............................................
end;
............................................
............................................
end.
В этом случае основная
программа будет предельно простой:
Program Graph_Objects;
Uses
GraphApp;
var
App: TGraphApp;
begin
App.Init;
App.Run;
App.Done
end.
В ней мы создаём
единственный экземпляр App
объекта-программы TGraphApp и
обращаемся к трём его методам.
Создание экземпляра объекта
ничуть не отличается от создание экземпляра переменной любого другого типа.
Просто в разделе описания переменных мы указываем имя переменной и её тип:
var
App: TGraphApp;
Получив это указание,
компилятор зарезервирует нужный объём памяти для размещения всех областей объекта
TGraphApp. Чтобы обратиться к тому
или иному объектному методу или полю, используется составное имя, причём первым
указывается не имя объектного типа, а имя соответствующей переменной:
App.Init;
App.Ryn;
App.Done;
Переменные объектного типа
могут быть статическими или динамическими, т.е. располагаться в сегменте данных
(статические) или в куче (динамические). В последнем случае мы могли бы
использовать такую программу:
Program Graph_Objects;
Uses
GraphApp;
type
PGrapgApp = ^TGraphApp;
var
App: PGraphApp;
begin
App:= New (PGraphApp, Init)
App^.Run;
App^.Done
end;
Для инициации динамической
переменной App используется вызов
функции New. В этом случае первым
параметром указываеися имя типа инициируемой переменной, а вторым
осуществляется вызов метода-конструктора, который нужен для настройки таблицы
виртуальных методов. Такой приём (распределение объектов в динамической памяти
с одновременной инициацией их ТВМ) характерен для техники ООП.
Ниже приводится возможный
вариант модуля GraphApp для данной
учебной прогаммы:
Unit
GraphApp;
Interface
Uses
GraphObj;
const
NPoins = 100; {количество точек}
type
{объект-программа}
TGraphApp = object
Points: array
[1..NPoints] of TPoint; {массив
точек}
Line: TLine;
{линия}
Rect: TRect; {прямоугольник}
Corcle: 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 экземпляров объекта TРoint, а так же экземпляры объектов 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;
Cofc.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 —
синонимы. Введение в ООП деструкторов носит, в основном, стилистическую
направленность — просто процедуру, разрушающую экземпляр объекта, принято называть деструктором. В
реальной практике ООП с деструкторами обычно связывают процедуры, которые не
только прекращают работу с объектом, но и освобождают выделенную для него
динамическую память.
В заключении следует
сказать, что формалистика ООП в рамках реализации этой технологии в Турбо
Паскале предельно проста и лаконична. Введение лишь шести зарезервированных
слов, из которых действительно необходимыми являются три (object, constructor, virtual),
весьма небольшая плата за мощный инструмент создания совреммнного програмного
обеспечения.
Список используемой
литературы:
·
Блашкин
И.И., Буров А.А. Новые возможности Turbo-Pascal 6.0. — Спб.: Изд-во “Макет”,
1992.
·
Бородич
Ю.С. и др. Паскаль для персональных компьютеров: Справ. пособие/ Ю.С.Бородич,
А.Н.Вальвачев, А.И.Кузьмич. — Мн.: Выш. шк.: БФ ГИТМП “НИКА”, 1991.
·
ВасильевП.П.
Турбо Паскаль — мой друг: М.: Компьютер, ЮНИТИ, 1995.
·
Джордейн
Р. Справочник программиста персональных компьютеров типа IBM PC, XT, AT: Пер. с
англ./ Предисл. Н.В.Гайского. — М.: Финансы и статистика, 1991.
·
Зуев
Е.А. Язык программирования Turbo Pascal 6.0. — М.: Унитех, 1992.
·
Мизрохи.
Turbo Pascal и объектно-ориентированное программирование. — М.: Финансы и
статистика, 1992.
·
Справочник
по процедурам и функциям Borland Pascal with Objects 7.0. — Киев: “Диалектика”,
1993.
·
Фаронов
В.В. Программирование на персональных ЭВМ в среде Турбо-Паскаль. — М.: Изд-во
МГТУ, 1990.
·
Фёдоров
А. Особенности программирования на Borland Pascal. — Киев: “Диалектика”, 1994.
·
Хершель
Р. Турбо Паскаль/ 2-е изд., перераб. — Вологда: МП “МИК”, 1991.
·
POWER
TOOLS PLUS. Процедуры поддержки для Turbo Pascal 4.0.: Справочное руководство
пользователя. Техническая документация.
|
|
|