10.4 Как используются модули
В Паскале определены 3 режима компиляции:
Compile
Make
Build.
При компиляции модуля или программы в режиме Compileвсе модули, которые они используют, должны быть откомпилированы, и храниться как машинный код с расширением.tpu, а не исходный текст на Паскале. При этом компилятор Паскаля предполагает, чтоpas-файл, в котором находится исходный текст модуля, а, следовательно, и соответствующийtpu-файл, имеет такое же имя (как в заголовкеUnit). Если имя модуля, например,MyUtilit, то компилятор будет искать файлMyUtilit . pas. Это предположение можно отменить с помощью директивы компилятораU. Пусть, например, в программе используются модулиDos,CrtиMyUtilit, который хранится в модулеUtil . pas. Тогда следует использовать следующее предложениеUses:
Uses Dos, Crt, {$U Util . pas}MyUtilit ;
При компиляции режиме Makeкомпилятор проверяет наличиеtpu-файлов для каждого объявленного модуля. Если какой-либо из файлов не обнаружен, компилятор пытается отыскать соответствующийpas-файл, и, если исходный файл найден, приступает к его компиляции. Кроме того, в этом режиме, если в исходный текст используемого модуля были внесены изменения, то модуль будет перекомпилирован.
В режиме Buildсуществующиеtpu-файлы игнорируются, и компилятор пытается отыскать и компилировать соответствующийpas-файл для каждого объявленного в разделеUsesмодуля.
Модуль может находиться в отдельном файле с расширением .tpu, а также его можно переслать в библиотеку модулей — в файл с расширением.tpl.
Для использования модуля применяется предложение Uses. Когда компилятор встречает предложениеUses, он прибавляет информацию из секции интерфейса каждого модуля к таблице символов программы и присоединяет машинный код из секции реализации к самой программе. Модули присоединяются в указанном порядке, т.е. в списке предложенияUsesмодуль должен быть указан после всех модулей, которые он использует.
10.5 Ссылки на описания модуля
Как только модуль включен в программу, все его описания из секции интерфейса становятся доступными для программы. Пусть, например, имеется модуль со следующей секцией интерфейса:
Unit MyUnit ;
Interface
Const
MyValue = 915 ;
Type
MyStars = ( Deneb, Antares, Betelgeuse ) ;
Var
MyWord : String [20] ;
Procedure SetMyWord ( Star : MyStars ) ;
Function TheAnswer : Integer ;
Можно написать следующую программу:
Program TestProg ;
Uses
MyUnit ;
Var
i : Integer ;
AStar : MyStars ;
Begin
WriteLn ( MyValue ) ;
AStar := Deneb ;
SetMyWord ( AStar ) ;
. . .
WriteLn ( MyWord ) ;
i := TheAnswer ;
WriteLn ( i )
End.
В программе, использующей модуль, некоторые идентификаторы могут быть переопределены. В этом случае программа будет использовать собственные определения, т.к. они описаны позже, чем определения в модуле. Однако и в этой ситуации можно ссылаться на идентификаторы из модуля, используя составные идентификаторы:
Program TestProg1 ;
Uses MyUnit ;
Const
MyValue = 22 ; {переопределение для MyValue }
Var i : Integer ;
AStar : MyStars ;
Function TheAnswer : Integer ; { переопределение для функции TheAnswer }
Begin
TheAnswer := 1
End ;
Begin
WriteLn ( MyValue ) ; {из программы }
WriteLn ( MyUnit . MyValue ) ; { из модуля }
AStar := Deneb ;
SetMyWord ( AStar ) ;
. . .
WriteLn ( MyWord ) ;
i := TheAnswer ; { из программы }
WriteLn ( i ) ;
i := MyUnit . TheAnswer ; { из модуля }
WriteLn ( i )
End.