Следует ожидать переводов разделов справочной системы Delphi, компиляций из учебников, переводы статей, «путевые заметки» и прочие интересности. Блог прежде всего ориентирован на студентов, но опытных людей я тоже буду рад видеть;-)
пятница, 18 марта 2011 г.
Структура и синтаксис модулей
Перевод из справочной системы Delphi
Модуль состоит из типов, констант, переменных и подпрограмм (функций и процедур). Каждый модуль определяется в своем собственном файле (.pas).
Файл модуля начинается заголовком, за которым следует ключевое слово interface. За ключевым словом interface следует раздел подключения модулей, который определяет зависимости модуля. Затем следует секция implementation, за которой идут необязательные секции initialization и finalization. Скелет файла с программным кодом модуля выглядит следующим образом:
unit Unit1; interface uses // список зависимостей. // секция Interface implementation uses // список зависимостей. // Реализация методов классов, процедур и функций. initialization // Программный код инициализации модуля. finalization // Программный код финализации модуля. end.
Модуль должен оканчиваться зарезервированным словом end с точкой.
11 Часть 1. Полезные модули: subprocess
может оказаться в файле с именем MainForm.pas, а файл, содержащий скомпилированный модуль должен быть MainForm.dcu. Имена модулей должны быть уникальны внутри проекта. Даже в том случае, когда файлы находятся в разных директориях, два модуля с одинаковыми именами не могут быть подключены в программе.
Секция Interface
Секция interface начинается с зарезервированного слова interface и продолжается до начала секции implementation. Секция interface объявляет константы, типы, переменные, процедуры и функции, которые доступны клиентам модуля, (другим модулям и программам которым необходимо воспользоваться элементами из этого модуля). Эти сущности обозначаются как public, поскольку программный код в других модулях может получать доступ к ним, так же, как если бы они были объявлены в этих модулях.
Объявления процедур и функций в секции interface содержат только их заголовки, то есть имя подпрограммы, параметры и тип возвращаемого значения (для функций). Блок, содержащий исполняемый код для процедур или функций следует в секции implementation. То есть объявления процедур и функций в секции interface работают как упреждающие объявления.
Объявление класса в секции interface должно включать все элементы класса: поля, свойства, процедуры и функции.
Секция interface может включать свой собственный раздел подключения модулей, который должен идти сразу же за ключевым словом interface.
Секция Implementation
Секция implementation начинается зарезервированным словом implementation и продолжается до начала секции initialization или, если эта секция отсутствует, до конца модуля. Секция implementation определяет процедуры и функции, которые объявлены в секции interface. Внутри секции implementation эти процедуры и функции могут быть определены в любом порядке. Вы можете опустить список параметров в заголовках публичных процедур и функций, когда вы объявляете их в секции implementation, но, если вы включили список параметров, он должен совпадать с их объявлением в секции interface.
Что делать, если Pycharm не видит библиотеку?
Кроме определения публичных процедур и функций, в секции implementation могут быть объявлены константы, типы (включая классы), переменные, процедуры и функции, которые являются частными (private) для модуля. То есть, в отличие от секции interface, сущности, объявленные в секции implementation недоступны снаружи модулей.
Секция implementation может включать свой собственный раздел подключения модулей, который должен следовать сразу за зарезервированным словом implementation. Идентификаторы, объявленные внутри секции implementation доступны для использования только непосредственно в секции implementation. Вы не можете ссылаться на эти идентификаторы из секции interface.
Секция Initialization
Секция initialization не является обязательной. Она начинается зарезервированным словом initialization и продолжается до начала секции finalization, или, если таковая отсутствует, — до конца модуля. Секция initialization содержит инструкции, которые выполняются при запуске программы в том же порядке, в котором они следуют в коде. То есть, например, если вы определили структуры для хранения данных, которые должны быть инициализированы, вы можете сделать это в секции initialization.
Для модулей, указанных в разделе подключения модулей секции interface, инструкции секций initialization модулей, подключенных к клиентам, выполняются в том же порядке, в котором они следуют в разделе подключения клиентов.
Устаревший синтаксис «begin . end.» все еще функционирует. Фактически зарезервированное слово «begin» может быть использовано вместо initialization, за которым может следовать произвольное количество инструкций (0 или больше). В программном коде, в котором используется устаревший синтаксис «begin . end.» Нельзя определить секцию finalization. В этом случае финализация осуществляется назначением процедуры переменной /ExitProc. Этот метод не рекомендован для развивающихся приложений, но вы можете встретить его в старом программном коде.
Секция Finalization
Секция finalization необязательна и может быть включена в модуль только в том случае, если он имеет секцию initialization. Секция finalization начинается зарезервированным словом finalization и продолжается до конца модуля. Она содержит инструкции, которые выполняются в момент завершения основного приложения (за исключением тех случаев, когда для завершения использована процедура Halt). Используйте секцию finalization для освобождения ресурсов, выделенных в секции initialization.
Секции Finalization выполняются в порядке, обратном выполнению секций initialization. Например, если ваше приложение инициализирует модули A, B, C (в таком же порядке), финализироваться они будут в порядке C, B, A.
Если, код инициализации модуля начинал выполняться, соответствующие секции финализации будут выполнены гарантированно при завершении приложения. По этому необходимо, чтобы инструкции секции finalization могли обрабатывать неполностью инициализированные данные (на тот случай, если при выполнении инструкций секции инициализации возникнет ошибка, и код этой секции не будет выполнен полностью).
Связи модулей и раздел подключения
В разделе подключения модулей перечисляются модули, используемые программой, библиотекой или модулем, в котором находится этот раздел подключения. Раздел подключения может быть добавлен в Файл проекта программы или библиотеки
- Секцию interface модуля
- Секцию implementation модуля
Большинство файлов проектов имеют раздел подключения так же, как и большинство модулей имеет секцию подключения. Секция implementation в модулях так же может содержать свой собственный раздел подключения.
Модули System и SysInit подключаются автоматически каждым приложением и не могут быть явно перечислены в разделе подключения. (Модуль System реализует подпрограммы ввода/вывода, работу со строками, операции с плавающей точкой, динамическое выделение памяти и так далее). Другие модули стандартных библиотек, например, SysUtils должны явно прописываться в разделе подключения. В большинстве случаев все необходимые модули включаются в раздел подключения средой разработки, по мере того, как вы добавляете или удаляете модули из своего проекта.
Чувствительность к регистру: при объявлении модулей и в разделах подключения модулей имена модулей должны совпадать с именами файлов модулей по регистру. В других случаях (при обращении к идентификаторам) имена модулей не чувствительны к регистру. Чтобы избежать проблем со связями модулей ссылайтесь явно на файл модуля: uses MyUnit in «myunit.pas»;
Если такое явное обращение присутствует в файле проекта, остальные файлы с программным кодом могут ссылаться на модуль через простой раздел подключения модулей, в котором нет необходимости соблюдать регистр:
Синтаксис раздела подключения модулей
Раздел подключения модулей состоит из зарезервированного слова uses, за которым следуют одно или больше имен модулей, разделяемых запятыми, за которыми следует точка с запятой. Примеры:
uses Forms, Main; uses Forms, Main; uses Windows, Messages, SysUtils, Strings, Classes, Unit2, MyUnit;
В разделе подключения модулей программы или библиотеки за именем любого модуля может следовать зарезервированное слово in и имя файла с программным кодом модуля с указанием (или без указания) пути к файлу в одинарных кавычках. Пути могут быть абсолютными или относительными. Примеры:
uses Windows, Messages, SysUtils, Strings in ‘C:ClassesStrings.pas’, Classes;
Используйте слово in после имени модуля в тех случаях, когда вам нужно указать файл с программным кодом модуля. Поскольку IDE ожидает, что имена модулей совпадают по регистру с их именами в файлах, в которых хранятся эти модули, обычно нет необходимости делать это. Использование in необходимо только когда местонахождение файла с программным кодом неясно. Например, когда:
- Вы использовали файл с программным кодом, который находится в директории, отличном от директория файла проекта;
- В различных директориях в путях поиска компилятора находятся модули с одинаковыми именами;
- Вы компилируете консольное приложение из командной строки и называете модуль с идентификатором, который не совпадает с именем файла, содержащего программный код модуля.
Компилятор полагается на конструкцию in . для того, чтобы определить, какие модуля являются частью проекта. Только те модули, которые указаны в разделе подключения в файле проекта (.dpr) с указанием имени файла могут считаться частью проекта. Остальные модули в разделе подключения используются проектом, но не принадлежат ему. Это различие не играет роли при компиляции, но влияет на инструментарий IDE, например, на Project Manager.
В разделе подключения модуля вы не можете зарезервированное слово in для указания компилятору на местоположение файла с программным кодом. Каждый модуль должен находиться в директориях, включенных в путь поиска компилятора. Более того, имена модулей должны совпадать с именами файлов, содержащих их программный код.
Множественные и косвенные связи модулей
Порядок, в котором модули следуют в разделе подключения, определяют порядок их инициализации и влияют на то, как компилятор выполняет поиск идентификаторов. Если два модуля объявляют переменные, константы, типы, процедуры или функции с одинаковыми именами, компилятор использует одну из модуля, указанного последним в разделе подключения. (Для доступа к идентификатору из другого модуля необходимо указать спецификатор: UnitName.Identifier.)
Раздел подключения должен включать только модули, используемые непосредственно программой или модулем, в котором они упоминаются. То есть, если модуль А ссылается на константы, типы, переменные, процедуры или функции, объявленные в модуле В, тогда А должен явно ссылаться на В. Если В в свою очередь ссылается на идентификаторы из модуля С, тогда А косвенно зависит от С. В этом случае С не должен добавляться в раздел подключения А, но компилятор должен иметь возможность найти В и С для того, чтобы обработать А.
Следующий пример иллюстрирует косвенную зависимость:
program Prog; uses Unit2; const a = b; // . unit Unit2; interface uses Unit1; const b = c; // . unit Unit1; interface const c = 1; // .
В этом примере Prog явно зависит от Unit2, который явно зависит от Unit1. То есть Prog косвенно зависит от Unit1. Поскольку Unit1 не указан в разделе подключения Prog, идентификаторы, объявленные в Unit1, недоступны для Prog.
Для компиляции клиентского модуля компилятору необходимо найти все модули, от которых явно или косвенно зависит клиент. До тех пор, пока программный код этих модулей не меняется, компилятору достаточно файлов .dcu.
Когда в секцию interface модуля внесены изменения, другие модули, которые зависят от этого изменения, должны быть перекомпилированы. Но когда изменения внесены только в секцию implementation или прочие секции модуля, зависимые модули могут не перекомпилироваться. Компилятор следит за этими зависимостями автоматически и перекомпилирует модули только когда это необходимо.
Циклические ссылки на модули
Когда модули явно или неявно ссылаются друг на друга, говорится, что модули обоюдозависимы. Обоюдные зависимости разрешаются в тех случаях, когда нет циклических путей, соединяющих раздел подключения одной секции interface и раздел подключения другой секции interface. Другими словами, если следовать по путям к модулям в их секциях interface, начиная с секции interface в одном модуле, не должно существовать возможности вернуться в исходный модуль. Для того, чтобы связь обоюдозависимых модулей была корректной, каждая циклическая ссылка должна вести через раздел подключения как минимум в одной секции implementation.
В простейшем случае два обоюдозависимых модуля не могут указывать друг друга в разделах подключения секций interface. Так, следующий пример приведет к ошибкам компиляции:
unit Unit1; interface uses Unit2; // . unit Unit2; interface uses Unit1; // .
Однако два модуля могут корректно ссылаться друг на друга, если одна из ссылок идет через секцию implementation:
unit Unit1; interface uses Unit2; // . unit Unit2; interface //. implementation uses Unit1; // .
Для снижения риска возникновения циклических ссылок лучше выполнять подключение модулей в секции implementation, когда есть возможность. Подключать модуль в разделе подключения секции interface необходимо только в том случае, когда секция interface одного модуля ссылается на идентификаторы из другого модуля.
Источник: pascal-study.blogspot.com
Как обратиться к процедуре общего модуля 1с. Общие модули. Различные контекст и общие модули
На общих модулях лежит обязанность хранения процедур и функций, которые вызываются из других мест системы 1С. Считается хорошим тоном размещение кода, вызывающегося несколько раз, в процедуре в общем модуле. Это правило универсально для всех конфигураций, поэтому любой разработчик 1С должен уметь работать с этими объектами конфигурации. Для этого нужно понимать все нюансы и уметь правильно использовать предоставленные платформой возможности.
Создание общего модуля в 1С
После создания функции в одном из модулей объекта возникла потребность использовать аналогичный алгоритм в другом месте. Самое правильно, что можно здесь сделать – перенести код в общий модуль, но перед этим необходимо создать его. Чтобы это сделать, нам нужно зайти в конфигуратор и в дереве конфигурации найти вкладку «Общие». Затем выделить «Общие модули» и воспользоваться кнопкой в виде белого плюса на зеленом кружке.
Справа откроются свойства добавленного общего модуля, и нам предстоит разобраться, что обозначает каждое из них. Они могут быть различной направленности, поэтому, перед тем как настраивать новый объект, желательно определиться, что мы там будем хранить. Если что, в будущем можно будет изменить свойства в соответствии с задачами:
- «Глобальный». Данный флаг ставится, если модуль предназначен для хранения процедур и функций, которые должны вызываться без указания имени модуля. Естественно, они должны быть экспортными, а их имена уникальными в разрезе всего глобального контекста. По использованию они не будут отличаться от стандартных функций платформы;
- «Клиент». Зависит от настроек системы и регламентирует, могут ли процедуры модуля выполняться на стороне клиента;
- «Сервер». Помечаются общие модули, в составе которых планируется помещать алгоритмы для выполнения на сервере;
- «Внешнее соединение». Процедуры модуля с активацией этого свойства смогут выполняться через подключение внешнего источника;
- «Вызов сервера». Отвечает за разрешения процедурам из модуля вызывать сервер, выполняясь на клиенте;
- «Привилегированный». Активация этой настройки позволит при работе кода процедур модуля не проверять права доступа. Вызвать общий модуль с такой настройкой можно только на сервере. Настройки «Клиент» и «Внешнее соединение» будут сброшены;
- «Повторное использование». Может принимать значения: «Не использовать», «На время сеанса», «На время вызова». При многократном вызове одной процедуры система может использовать рассчитанные ранее данные в рамках процедуры (вызов) или жизни всего сеанса (запуска 1С). Стоит быть очень осторожным с этой настройкой, так как из-за неправильного использования таких модулей могут возникать ошибки.
Бывают ситуации, когда требуется создать общий модуль с вызовами процедуры на сервере и клиенте с отличиями в алгоритме. Для разграничения кода используются директивы препроцессора с проверкой. В результате для серверного вызова это будет один код, а для клиентского – другой.
Процедура АлгоритмСерверКлиент() Экспорт #Если ТонкийКлиент Тогда // код выполняется, если вызов процедуры пришел с клиента ПоказатьОповещениеПользователя(«На клиенте»); ИначеЕсли Сервер Тогда // код выполняется, если вызов процедуры пришел с сервера ПеременнаяСервер = «Серверный вызов»; #КонецЕсли КонецПроцедуры
Пример переноса кода в общий модуль 1С
Рассмотрим ситуацию, когда у нас два события на форме документа задействуют одну процедуру перемножения количества и цены в табличной части. Это достаточно распространенный алгоритм, так как он встречается во многих документах закупки и реализации. Перенесем код процедуры в общий модуль, который необходимо предварительно создать, чтобы получить возможность использовать этот код в других документах.
Так как для нашей задачи нам хватает вызова с клиента и не нужны данные из базы, ставим только флаг «Клиент». Если вы хотите в дальнейшем использовать этот же модуль для более сложных расчетов, то отметьте в свойствах еще и «Сервер». Подготовительный этап завершен и можем переходить к написанию кода.
Создадим экспортную процедуру в модуле и перенесем туда алгоритм расчета суммы из процедуры в модуле формы. В качестве параметра процедуры на входе будет использоваться строка табличной части. В модуле формы документа меняем вызовы процедуры в том же модуле на вызов процедуры из общего модуля.
Процедура РассчитатьСтроку(СтрокаТабличнойЧасти) Экспорт СтрокаТабличнойЧасти.Сумма = СтрокаТабличнойЧасти.Количество * СтрокаТабличнойЧасти.Цена; КонецПроцедуры
При запуске системы мы не заметим разницы, но такую структуру кода читать и сопровождать намного удобнее. Конечно, в данном примере количество кода не может показать всей пользы. В случае сложного алгоритма для десятков объектов конфигурации выигрыш в объеме кода и его структуры скажется и на быстродействии системы. Помимо этого опытные разработчики 1С рекомендуют в модулях формы не описывать алгоритмы, а помещать их в правильно настроенные общие модули.
При разработке общих модулей следует учитывать общепринятые правила по их созданию:
- Помещать в отдельный общий модуль процедуры и функции, относящиеся к сходному функционалу;
- В наименовании модуля отражать его принадлежность к контексту (Клиент, Сервер) и избегать общих слов (обработчики, процедуры и т.д.);
- Разделять внутреннюю серверную логику приложения и клиентскую для интерфейса;
- Будьте внимательны, создавая глобальный общий модуль. Отсутствие необходимости обращаться к процедуре через имя модуля может привести к путанице, особенно, если систему поддерживает несколько групп разработчиков.
Правильно созданные модули помогут вам намного быстрее ориентироваться в структуре конфигурации и делать доработки. Если вы видите возможность сделать полезную функцию универсальной и вынести ее в общий модуль, то сделайте это. В будущем вы и ваши коллеги будете благодарны за это решение.
Общие модули 1С — объект метаданных конфигурации 1С 8.3 и 8.2, который хранит в себе программный код, который часто вызывается в конфигурации. Функцию/процедуру можно вызвать из любого места конфигурации (если она экспортная).
Как использовать общий модуль
Хороший тон — поместить процедуру или функцию в общий модуль, если она вызывается в более чем одном месте. Во-первых, если процедура корректируется, её надо править только в одном месте. Во-вторых, этим достигается больший порядок в коде.
Типичный пример общего модуля — обработка проведения по какому-то регистру, получение количества разницы рабочих дней, пересчет курсов валют, пересчет количества/цены/суммы в табличной части и другие функции.
Свойства общих модулей
Одно из основных особенностей общих модулей от других модулей — нельзя объявлять общие переменные.
Получите 267 видеоуроков по 1С бесплатно:
Рассмотрим подробнее палитру свойств общего модуля:
- Глобальный — если флаг установлен, функции и процедуры из этого модуля становятся доступны в глобальном контексте. Т.е. их можно вызвать в любом месте конфигурации, обращаясь без названия общего модуля. Однако добавляется условие — название процедур и функций в этом общем модуле должны быть уникальны в рамках глобального контекста.
- Сервер — процедуры и функции данного общего модуля могут быть выполнены на сервере.
- Внешнее соединение — программные коды данного общего модуля могут быть выполнены при подключении внешним источником (например, COM).
- Клиент (управляемое приложение) — процедуры и функции данного общего модуля могут быть использованы в толстом клиенте в режиме управляемого приложения.
- Клиент (обычное приложение) — программные коды данного общего модуля могут быть использованы в толстом клиенте в режиме обычного приложения.
- Вызов сервера — флаг, разрешающий на клиенте использовать процедуры и функции из этого общего модуля.
- — если установлена Истина, в этом общем модуле будет отключена проверка прав доступа.
- Повторное использование — определяет настройки возвращаемых значений, если опция включена, то после первого выполнения система запомнит значение для данных входных параметров и будет возвращать уже готовое значение. Может принимать следующие значения: не используется — отключение, на время вызова — на время выполнения определенной процедуры, на время сеанса — пока пользователь не закрыл сеанс (программу).
Если Вы начинаете изучать 1С программирование, рекомендуем наш бесплатный курс (не забудьте
Модули платформы 1С:Предприятие 8.3, 8.2
Общие модули
Функции, которые объявлены с флагом «экспорт» в таком модуле, можно вызывать из любых мест конфигурации. Вызов делается через ИмяОбщегоМодуля.ИмяФункции().
В таких модулях отсутствует раздел переменных.
Выполнение общих модулей зависит от выставленных параметров в их свойствах:
Флаг «Глобальный»
Если этот флаг установлен, то контекст такого модуля становится глобальным. То есть при обращении к его экспортным функциям не нужно указывать имя модуля. Но имена его экспортных функций должны быть уникальными в пределах глобального контекста конфигурации.
Флаг «Сервер»
Функции такого модуля могут выполняться на сервере.
Флаг «Клиент (обычное приложение)»
Функции такого модуля могут выполняться на клиенте в режиме обычного приложения.
Флаг «Клиент (управляемое приложение)»
Функции такого модуля могут выполняться на клиенте в режиме управляемого приложения.
Флаг «Вызов сервера»
Флаг доступен для модулей с установленным флагом «Сервер». Разрешает вызов на клиенте экспортных функций этого модуля (которые будут выполняться на сервере).
Флаг «Внешнее соединение»
Экспортные функции такого модуля могут быть вызваны при подключении из внешнего источника.
Флаг «Привилегированный»
В модуле с таким флагом будет отключена проверка прав. Подходит для повышения производительности или действий по администрированию.
Параметр «Повторное использование»
Если включить данный параметр, то возвращаемые значения экспортных функций будут кэшироваться сразу после первого вызова. Кэширование возможно на время вызова (время исполнение определенной процедуры) или на время сеанса пользователя.
Модуль приложения
Предназначен для обработки событий запуска и завершения приложения. Бывает двух видов: для обычного и управляемого приложений.
Не следует его перегружать, так как это влияет на время запуска приложения.
Модуль сеанса
Специальный модуль, который используется для инициализации параметров сеанса. Нужен для того, чтобы не дублировать код в различных модулях приложений.
Использовать его следует осторожно, так как модуль может выполняться несколько раз, а также выполняться без дальнейшего запуска базы. Выполняется до модулей приложения.
С уважением, (преподаватель и разработчик ).
Читайте также
Источник: bmwworkshop.ru
Учебники. Программирование для начинающих.
і іпрограммыі АДДДЩ ^ і ЪДДДДДДДДДДДї ^ АДДДДЩ АДДДЩ
і АДДДДДДДДДЩ і АД>іпредложениеГДЩ
АДДДДДДДДДДДДДДДДДДДДДДЩ і uses і
і ЪДДДДДДДї ЪДДДДДДДДДДДДДї
АДДДДДДДЩ АДДДДДДДДДДДДДЩ і ЪДДДї ЪДДДДДДДДДї ЪДДДї ^
АД>і ( ГД>іпараметрыГД>і ) ГДЩ
АДДДЩ іпрограммыі АДДДЩ
параметры программы ДДДД>і список ГДДДД>
Если заголовок программы присутствует, он является чисто декоративной деталью и компилятор его игнорирует.
Оператор uses
Оператор uses идентифицирует все модули, используемые программой, включая непосредственно используемые модули и модули, используемые этими модулями.
ЪДДДДї ЪДДДДДДДДДДДДДї ЪДДДї
предложение uses ДД>іusesГДДВДД>іидентификаторГДДДДД>і ; ГДДД>
АДДДДЩ і АДДДДДДДДДДДДДЩ ^ АДДДЩ
Модуль System всегда используется автоматически. Для поддержки таких средств, как файловый ввод-вывод, обработка строк, операции с плавающей запятой, динамическое распределение памяти и других этот модуль реализует весь нижний уровень, а также обслуживающие фоновые программы.
Паскаль, в свою очередь, обслуживает многие стандартные модули, такие, как Dos и Crt. Это не происходит автоматически: вы должны обязательно включить их в оператор uses. Например:
Чтобы найти файл, содержащий скомпилированный модуль, компилятор усекает указанное в операторе uses имя модуля до первых восьми файлов и добавляет расширение файла. Если целевой платформой является DOS, расширением будет .TPU. Если целевая платформа — Windows, то расширением файла будет .TPW. Если целевой платформой является защищенный режим DOS, то расширением файла будет .TPP. Хотя имена файлов усекаются, в операторе uses должен указываться полный идентификатор модуля.
Синтаксис модулей
Модули являются основой модульного программирования. Они используются для создания библиотек, которые могут включаться в различные программы (при этом становится необязательным иметь в наличии исходный код), а большие программы могут подразделяться на логически связанные модули.
ЪДДДДДДДДДї ЪДДДї ЪДДДДДДДДДДї
модуль ДДДДД>ізаголовокГДД>і ; ГДД>іинтерфейс-ГДДДї
і модуля і АДДДЩ іный разделі і
АДДДДДДДДДЩ АДДДДДДДДДДЩ і
і ЪДДДДДДДДДДї ЪДДДДДДДДДДДДДї ЪДДДї
АД>і раздел ГДДД>і раздел ГДД>і . ГДД>
В заголовке модуля определяется имя модуля.
заголовок модуля ДДД>іunitіДД>іидентификатор модуляіДДДД>
Имя модуля используется при ссылке на модуль в предложении использования. Это имя должно быть уникальным, так как два модуля с одним именем не могут одновременно использоваться.
Имя исходного файла модуля и двоичного файла должны совпадать с идентификатором модуля, усеченным до первых 8 символов. Если это не так, то компилятор не сможет найти исходный и/или двоичный файл при компиляции использующей этот модуль программы.
Интерфейсная секция
В интерфейсной секции описываются те константы, типы, переменные, процедуры и функции, которые являются глобальными, то есть доступными основной программе (программе или модулю, которые используют данный модуль). Основная программа имеет доступ к этим элементам, как если бы они были описаны в модуле, являющимся вложенным по отношению к данной программе.
і і і ЪДДДДДДДДДДДї^ ^ і ЪДДДДДДДДДДДДДДДДДДї ^ і
АДДДДДДДДДЩ АД>і оператор ГЩ і ГД>і раздел описания ГДґ і
і usesі і і і констант і і і
АДДДДДДДДДДДЩ і і АДДДДДДДДДДДДДДДДДДЩ і і
і і ЪДДДДДДДДДДДДДДДДДДї і і
і ГД>і раздел описания ГДґ і
і і і типов переменных і і і
і і АДДДДДДДДДДДДДДДДДДЩ і і
і і ЪДДДДДДДДДДДДДДДДДДї і і
і ГД>і раздел описания ГДґ і
і і іпеременных і і і
і і АДДДДДДДДДДДДДДДДДДЩ і і
і і ЪДДДДДДДДДДДДДДДДДДї і і
і АД>іраздел заголовков ГДЩ і
і іпроцедур и функцийі і
і АДДДДДДДДДДДДДДДДДДЩ і
процедур и функций
і ЪДДДДДДДДДї ЪДДДї
і іпроцедурыі ^ АДДДЩ і ЪДДДДДДДДДї ЪДДДї ^
і АДДДДДДДДДЩ і АД>ідирективаГДД>і ; ГДЩ
і ЪДДДДДДДДДДДДДДДДДї і і inline і АДДДЩ
АД>ізаголовок функцииГДЩ АДДДДДДДДДЩ
В том случае, если процедура или функция является процедурой или функцией типа inline, в интерфейсной секции содержится только список заголовков процедур или функций. Модуль процедуры или функции следует дальше в секции реализации. Заметим, что заголовок процедуры или функции может дублироваться и быть здесь таким же, как в интерфейсной секции. Вам не нужно задавать здесь список формальных параметров, но если вы это сделали и если описание в интерфейсной секции и секции реализации не совпадают, то компилятор во время компиляции выдаст сообщение об ошибке.
Секция реализации
В секции реализации определяются модули всех глобальных процедур или функций. В ней также описываются константы, переменные, процедуры и функции, являющиеся локальными, то есть недоступными основной программе.
і ЪДДДДДДДДДДДДДДї ЪДДДДДДДДДДДДДДДДДДї
АД>іimplementationГДВДДДДДДДДДДДДДДДДДД>і раздел описаний ГДД>
АДДДДДДДДДДДДДДЩ і ЪДДДДДДДДДДДї^ АДДДДДДДДДДДДДДДДДДЩ
АД>і оператор ГЩ
По механизму действия описания процедур и функций в интерфейсная секция аналогична опережающему описанию, хотя директива forward не указывается. Таким образом, эти процедуры и функции могут быть определены (и к ним можно обращаться в любой последовательности) в секции реализации.
Допускается дублирование заголовков процедур и функций из интерфейсной части. Вам не нужно при этом задавать список формальных параметров, но если вы это делаете, компилятор на этапе компиляции в случае несовпадения описаний в интерфейсной части и секции реализации будет выдавать сообщение об ошибке.
Секция инициализации
Секция инициализации является последней секцией модуля. Она может состоять либо из зарезервированного слова end (в этом случае модуль не содержит кода инициализации), либо из операторной части, которая должна выполняться для инициализации модуля.
секция инициализации ДДДВДД>іendГДДДДДДДДДДДДДДДДДД>
і ЪДДДДДДДДДДДДДДДДДї і
Секции инициализации модулей, которые используются программой, выполняются в том же порядке, в каком модули указаны в операторе uses.
Косвенные ссылки на модули
В операторе uses в основной программе должны содержаться имена всех модулей, непосредственно или косвенно используемых основной программой. Рассмотрим следующий пример:
uses Unit1, Unit2
В данном примере Unit12 непосредственно зависит от Unit1, а Prog непосредственно зависит от Unit2. Кроме того, Prog зависит косвенно от Unit1 (через Unit1), хотя ни один из описанных в Unit1 идентификаторов в Prog не доступен.
Для компиляции программы компилятор должен иметь возможность находить все модули, от которых она прямо или косвенно зависит. Поэтому, для компиляции Prog компилятор должен иметь возможность найти и Unit1, и Unit2, иначе возникнет ошибка.
Когда в интерфейсную часть модуля вносятся изменения, другие модули, использующие этот модуль, должны быть заново скомпилированы. При использовании команд Make или Build компилятор делает это автоматически. Однако, если изменения коснулись только секции реализации или секции инициализации, то другие модули, в которых используется этот модуль, перекомпилировать не нужно. В предыдущем примере, если интерфейсная часть модуля Unit1 изменилась (например, с = 2), то модуль Unit2 нужно перекомпилировать. Изменение же секции реализации (например, d = 1) не требует перекомпиляции Unit2.
При компиляции модуля в Borland Pascal на основе контрольной суммы интерфейсной секции вычисляется номер версии модуля. В предыдущем примере при компиляции модуля Unit2 в скомпилированной версии модуля Unit2 сохраняется номер версии модуля Unit1. При компиляции основной программы номер версии модуля Unit1 сравнивается с номером версии, сохраненным в модуле Unit2. Если номера версий не совпадают, что свидетельствует об изменении в интерфейсной части модуля Unit1 со времени последней компиляции модуля Unit2, компилятор, в зависимости от режима компиляции, выдает сообщение об ошибке или перекомпилирует модуль Unit2 (в зависимости от режима компиляции).
Перекрестные ссылки на модули
Размещение в секции реализации оператора uses позволяет «скрыть» внутренние детали модуля, поскольку используемые в секции реализации модули оказываются «невидимыми» для того, кто этот модуль использует. Более важным, однако, является то, что это позволяет вам строить взаимозависимые модули.
В следующей программе показаны два модуля, которые «используют» друг друга. Основная программа Circular использует модуль с именем Display. Модуль Display содержит в своей интерфейсной секции одну программу WriteXY, которая имеет три параметра: пару координат (x,y) и сообщение для вывода на экран. WriteXY перемещает курсор в точку (x,y) и выводит там сообщение. В противном случае она вызывает простую программу обработки ошибки.
Пока мы не видим здесь ничего интересного: процедура WriteXY просто используется вместо процедуры Write. Однако далее, когда программа обработки ошибки будет выводить сообщение на экран, начинаются перекрестные ссылки (ведь при этом она снова использует WriteXY). Таким образом, мы имеем процедуру WriteXY, вызывающую процедуру обработки ошибки SwapError, которая в свою очередь вызывает WriteXY для вывода сообщения на экран. Если у вас уже от всего этого закружилась голова, не беда. Давайте рассмотрим исходный код в примере и увидим, что все это не столь уж запутано.
Основная программа Circular очищает экран и выполняет три обращения к процедуре WriteXY:
WriteXY(1, 1, ‘Левый верхний угол экрана’);
WriteXY(100, 100, ‘За пределами экрана’);
WriteXY(81 — Lenght(‘Снова в экран..’), 15,
Взгляните на координаты (x,y) при втором обращении к процедуре WriteXY. В точке с координатами (100,100) на 80х25-символьном экране вывести текст невозможно. Давайте теперь посмотрим, как работает процедура WriteXY. Далее приведен текст исходного кода модуля Display, в котором содержится процедура WriteXY. Если координаты (x,y) являются допустимыми, она выводит на экран сообщение.
В противном случае она выводит сообщение об ошибке.
procedure WriteXY(X,Y : integer, Message : string);
procedure WriteXY(X,Y : integer, Message : string);
if (X in [1..80] and Y in [1..25] then
ShowError(‘Неверные координаты в процедуре WriteXY’);
Процедура ShowError, вызываемая в процедуре WriteXY, показана в приведенном далее исходном коде модуля Error. Она всегда выводит сообщение об ошибке на 25-й строке экрана.
procedure ShowError(ErrMsg : string);
procedure ShowError(ErrMsg :string);
WriteXY(1,25, ‘Ошибка: ‘+ ErrMsg);
Обратите внимание, что операторы uses в секции реализации обоих модулей (Display и Error) ссылаются друг на друга. Эти два модуля могут ссылаться друг на друга в секции реализации благодаря тому, что Borland Pascal может для обеих модулей выполнять полную компиляцию интерфейсных секций. Другими словами, компилятор воспринимает ссылку на частично скомпилированный модуль A в секции реализации модуля В, если интерфейсные секции модуля A и модуля В не зависят друг от друга (и, следовательно, строго соблюдаются правила Паскаля, касающиеся порядка описания).
В случае взаимозависимости интерфейсных секций модулей вы получите ошибку из-за перекрестных ссылок.
Совместное использование описаний
Можно модифицировать процедуру WriteXY таким образом, чтобы она воспринимала дополнительный параметр, задающий прямоугольное окно на экране:
procedure WriteXY(SomeWindow : WindRec;
procedure ShowError(Somewindow : WindRec; ErrMsg : string);
Нужно учитывать, что две процедуры находятся в разных модулях. Даже если вы описываете WindData в интерфейсной секции одного модуля, то нет такого допустимого способа, с помощью которого это описание могло бы быть доступно в другом модуле. Решение состоит в том, чтобы описать третий модуль, в котором содержится только определение записи WindRec:
X1, Y1, X2, Y2 : integer;
В добавление к тому, что модификация кода процедур WriteXY и ShowError позволяет использовать новый параметр, в интерфейсной секции модулей Display и Error теперь может использоваться WindData. Это допустимо, так как модуль WindData не зависит от своего оператора uses, а модули Display и Error ссылаются друг на друга только в соответствующих секциях реализации.
Взаимозависимые модули могут быть полезны в отдельных ситуациях, но использовать их надо аккуратно. Если вы будете применять их так, где это не требуется, программу станет сложней обслуживать, и она будет больше подвержена ошибкам.
Источник: programm.ws