6.11. Особенности работы с модулями

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

- 128 -

| UNIT Colors; { Модуль, вводящий цветовые константы }

| INTERFACE

| TYPE

| ColorType = Array[0..15] of Byte;{определено 16 цветов}

| CONST

| Black : Byte = 0; Blue : Byte = 1;

| Green : Byte = 2; Cyan : Byte = 3;

| Red : Byte = 4; Magenta : Byte = 5;

| Brown : Byte = 6; LightGray : Byte = 7;

| DarkGray : Byte = 8; LightBlue : Byte = 9;

| LightGreen : Byte = 10; LightCyan : Byte = 11;

| LightRed : Byte = 12; LightMagenta : Byte = 13;

| Yellow : Byte = 14; White : Byte = 15;

| VAR

| CurrColors: ColorType absolute Black; {текущие значения}

| PROCEDURE SetMonoColors; (настройка цветов на режим MONO}

| PROCEDURE SetColorColors; (настройка цветов в режим ЦВЕТ}

| IMPLEMENTATION

| CONST ( значения констант для режимов: }

| ColorColors : ColorType =

| (0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15);

| MonoColors : ColorType =

| (0,1,7,7,7,7,7,7,7,7, 7, 7, 7, 7,15,15);

| PROCEDURE SetMonoColors;

| BEGIN

| CurrColors := MonoColors;

| END;

| PROCEDURE SetColorColors;

| BEGIN

| CurrColors := ColorColors;

| END;

| VAR

| ch : Char;

| BEGIN

| { Запрос и настройка на соответствующий режим: }

| Write('Тип Вашего монитора(Ц-цветной, М-монохромный)?');

| ReadLn( ch ):

| if ch in ['M', 'm','М', 'м']

| then

| SetMonoColors;

| END.

| Примечание: для того чтобы модуль корректно вводил константы надо, чтобы в директиве USES программы он стоял после модуля CRT.

Рис. 6.19

- 129 -

но подключают системные модули Турбо Паскаля (из библиотеки TURBO.TPL) и лишь затем все остальные, хранящиеся в виде TPU-или даже PAS-файлов.

Порядок подключения может влиять на доступность библиотечных типов, данных и даже процедур. Например, если модули U1 и U2 описывают в разделах объявлений одноименные тип T, переменную V и процедуру P, но реализуют их по-разному, то после подключения модулей директивой

USES

U1, U2;

обращения к T, V и P будут эквивалентны обращениям к содержимому библиотеки U2. Более того, если далее в основной программе эти имена объявляются заново, то они «замещают» собой имена, относящиеся к модулю. (Заметим, что повтор идентификаторов в модулях и программе не является ошибкой, но всегда будет неверным введение одинаковых имен в пределах одного модуля или программы.) Тем не менее доступ к содержимому любого модуля всегда возможен, если перед идентификатором уточнять его местонахождение, указывая имя модуля. Так, если нам нужны T, V и P именно из модуля U1, то обращаться к ним надо, как к

U1.T, U1.V и U1.P( ... ).

Переменная V из модуля U2 должна превратиться в U2.V и т.д.

Таким образом, следует учитывать порядок подключения, если модули вводят одинаковые идентификаторы, или гарантировать корректность обращений, указывая явно принадлежность библиотечных подпрограмм, данных или типов.

Другой особенностью использования модулей является решение проблемы закольцованности. Иногда может возникнуть ситуация, когда модуль U1 использует что-либо из модуля U2 и в то же время U2 обращается к процедурам модуля U1. Решение подобных проблем зависит от того, в каком разделе возникла закольцованность. Если оба модуля подключают друг друга директивой USES в разделе IMPLEMENTATION, то закольцованность автоматически разрешается компилятором Турбо Паскаля. Но если хотя бы один из модулей подключает другой в разделе INTERFACE, то разрешать противоречие придется программным путем. Проблема будет решена, если ввести третий модуль и поместить в него все те типы, переменные или подпрограммы из первых двух модулей, которые ссылаются друг на друга. После этого надо их удалить из обоих исходных модулей, а взамен подключить созданный из них третий модуль.

- 130 -

Подобный прием очень часто используется для введения общих для программы и (или) нескольких независимых модулей типов, констант и переменных. Создается модуль из одних только описаний, как на рис. 6.20.

| UNIT Conmon;

| INTERFACE

| TYPE

| ComArrayType = Array [0..99] of LongInt;

| CONST

| MaxSize = 100;

| VAR

| ComArray : ComArrayType;

| Flag : Byte;

| {и т.п.}

| IMPLEMENTATION

| END.

Рис. 6.20

Модуль подключается директивой USES везде, где требуется обращение к общим переменным и константам или вводятся новые переменные общего типа.