Модуль (UNIT) в Турбо Паскале — это специальным образом оформленная библиотека определений типов, констант, переменных, а также процедур и функций. Модуль в отличие от программы не может быть запущен на выполнение самостоятельно: он может только участвовать в построении программы или другого модуля. Но в отличие от фрагментов, подключаемых к программе при компиляции директивой {$1 ИмяФайла}, модули предварительно компилируются независимо от использующей их программы. Результатом компиляции модуля является файл с расширением.TPU (Turbo Pascal Unit). Для того чтобы подключить модуль к программе (или другому модулю), необходимо и достаточно указать его имя в директиве USES.
Все системные библиотеки Турбо Паскаля реализованы как модули, и чтобы воспользоваться, например, библиотеками функций операционной системы DOS и графики Graph, нужно только указать директиву
USES
DOS, Graph;
и дальше использовать любое содержимое библиотек, как будто оно предопределено в языке.
В Турбо Паскале возможность модульного построения чрезвычайно полезна в двух случаях. Во-первых, модули очень удобны для {124} построения собственных библиотек процедур и функций, которые впоследствии могут подключаться к разным программам, не требуя при этом никаких переделок. Во-вторых, именно модульность позволяет создавать программы практически любого размера. Дело в том, что ни программа, ни модуль, не могут произвести выполнимый код объемом более 64K, если они не используют при построении другие модули. В то же время сумма объемов модулей, составляющих программу, ограничена лишь объемом ОЗУ ПЭВМ, и то, если не используется оверлейная структура. Общая структура модуля приводится на рис. 6.17.
UNIT ИмяМодуля; INTERFACE <-— начало раздела объявлений USES { используемые при объявлениях модули: } Имя_Модуля1, Имя_Модуля2,...; CONST Блок объявления библиотечных констант TYPE Блок объявления библиотечных типов VAR Блок объявления библиотечных переменных Заголовки библиотечных процедур и (или) функций IMPLEMENTATION <—- начало раздела реализации USES { используемые при реализации модули:} Имя_Модуля101, Имя_Модуля202,...; CONST Блок объявления внутренних констант TYPE Блок объявления внутренних типов VAR Блок объявления внутренних переменных LABEL Блок описания меток блока инициализации BEGIN Блок инициализации модуля END. |
Рис. 6.17
Модуль разделяется на четыре части:
— заголовок модуля (UNIT имя);
— раздел объявлений или интерфейс (INTERFACE);
— раздел реализации (IMPLEMENTATION);
— раздел инициализации (между BEGIN и END).
Все блоки, составляющие эти разделы (см. рис. 6.17), являются необязательными, и могут отсутствовать (как могут и появляться неоднократно). Обязательные слова, входящие в модуль, продемонстрированы на рис. 6.18, где показан пустой модуль. {125}
UNIT Пустой; INTERFACE IMPLEMENTATION END. |
Рис. 6.18
Обращаем внимание на отсутствие точек с запятой после ключевых слов. Если не вводится раздел инициализации, то начинающее его слово BEGIN не ставится.
Заголовок модуля вводит имя, по которому модуль будет подключаться к другим программам. Имя должно быть уникальным (не иметь повторов внутри модуля) и соответствовать имени файла (с расширением.PAS), хранящего исходный текст модуля (а после компиляции на диск имени файла с расширением.TPU).
Имя модуля как идентификатор имеет до 64 значащих символов. Но имя файла на диске не может превышать длину в восемь символов! Тем не менее имя модуля не обязательно ограничивать восемью символами. Пусть их будет больше, но при этом первые восемь должны совпадать с именем файла. А в основной программе в директиве USES должно стоять полное имя, как и в заголовке самого модуля.
Раздел объявлений, начинающийся словом INTERFACE, содержит описания типов, констант и переменных, которые будут привноситься в программу при подключении модуля. В нем же описываются заголовки процедур и функций, составляющих собственно библиотеку подпрограмм. В разделе объявлений указываются только заголовки, потому что информация о содержимом подпрограмм модуля не нужна на этапе компиляции, а используется только при компоновке программы. Исключение составляют процедуры с директивой inline (см. разд. 14.7.2). Они могут целиком задаваться в разделе объявлений. Недопустимы заголовки с директивами interrupt (см. разд. 16.6) и forward.
Если при объявлении типов, данных или подпрограмм используются константы и типы, введенные в других модулях (библиотеках), то эти модули должны быть перечислены в директиве USES сразу после ключевого слова INTERFACE. В модулях директива USES может появляться дважды. Второй раз — в разделе реализации. Рекомендуется указывать в разделе объявлений только те модули, которые необходимы. Прочие лучше подсоединить в другом месте. {126}
Раздел реализации состоит, как правило, из тел процедур и функций, объявленных в разделе объявлений. Как и в случае с опережающим описанием (forward), тела подпрограмм могут иметь сокращенный заголовок: без указания параметров. Но если заголовок дан в полном виде, то он должен в точности соответствовать данному ранее объявлению.
В разделе реализации могут быть введены свои типы, константы и переменные. Они будут считаться глобальными по отношению к подпрограммам этого раздела, а также операторам раздела инициализации (если последний имеется). В программе, подключающей модуль, объявленные при реализации данные и типы недоступны.
Если в телах процедур или при заданиях типов либо переменных необходимо что-либо, объявленное в других модулях, и эти модули не попали в директиву USES раздела объявлений, то их надо перечислить в директиве USES сразу после слова IMPLEMENTATION.
В разделе реализации могут описываться подпрограммы, участвующие в работе объявленных процедур и функций, но сами не являющиеся объявленными.
Раздел инициализации завершает текст модуля. Если он отсутствует, то просто ставится слово END с точкой после конца последнего тела подпрограммы раздела реализации. В противном случае ставится слово BEGIN, и далее программируются действия, которые будут произведены перед выполнением основной программы (работа скомпилированной программы всегда начинается с выполнения блоков инициализации используемых ею модулей, и лишь потом выполняется основной блок самой программы). Обычно в разделе инициализации происходит заполнение стартовыми значениями библиотечных переменных и какие-нибудь одноразовые действия, которые должны выполниться именно в начале программы. На рис. 6.19 приводится пример модуля с инициализацией.