begin
...
B(i-1);
end;
procedure B(i: integer);
begin
...
A(i div 2);
end;
Запрещено делать опережающее объявление для уже описанной подпрограммы.
Для методов ключевое слово forward запрещено. В нем нет необходимости, потому что можно вызывать методы, определенные в теле класса позднее.
Перегрузка имен подпрограмм
В одном пространстве имен может быть определено несколько процедур или функций с одним именем, но разным количеством или типами параметров. Имена таких процедур и функций называются перегруженными, а их создание - перегрузкой имен. Разновидностью перегрузки имен является перегрузка операций.
При вызове перегруженной процедуры или функции выбирается та версия, у которой типы формальных параметров совпадают с типами фактических или наиболее близки к ним. Например, если имеются описания
procedure p(b: byte);
begin
end;
procedure p(r: real);
begin
end;
то при вызове p(1.0) будет выбрана перегруженная версия с параметром типа real (точное соответствие), а при вызове p(1) будет выбрана перегруженная версия с параметром типа byte (при этом произойдет преобразование фактического параметра типа integer к типу byte).
Заметим, что, в отличие от Object Pascal, использовать при перегрузке служебное слово overload не нужно.
Если ни одна версия в текущем пространстве имен не подходит к данному вызову, то возникает ошибка компиляции. Если две и более версии одинаково хорошо подходят к данному вызову, то также возникает ошибка компиляции, заключающаяся в неоднозначности выбора подпрограммы. Например, если имеются описания
procedure p(i: integer; r: real);
begin
end;
procedure p(r: real; i: integer);
begin
end;
то при вызове p(1,2) оба они одинаково подходят, что приводит к неоднозначности.
Запрещено перегружать подпрограмму другой подпрограммой с тем же количеством и типами параметров, отличающихся лишь тем, передается ли параметр по значению или по ссылке. Например, описания
procedure p(i: integer);
и
procedure p(var i: integer);
считаются одинаковыми.
Возвращаемое значение функции не участвует в разрешении перегрузки, т.е. перегружаемые функции не могут различаться только типами возвращаемых значений.
Алгоритм перегрузки имен при наличии нескольких подключенных модулей, а также алгоритм перегрузки имен методов имеют особенности. Основная особенность этих алгоритмов состоит в том, что они работают через границы пространств имен.
Поиск перегруженного имени глобальной подпрограммы при наличии нескольких подключенных модулей происходит во всех модулях. При этом вначале осуществляется просмотр текущего модуля, а потом всех модулей, подключенных в секции uses, в порядке справа налево. Если при этом поиске находится объект, который не может перегружать предыдущие (например, перегружается процедура, а найдено имя переменной), то цепочка перегрузки заканчивается, и поиск наилучшей перегруженной подпрограммы идет среди найденных до этого момента. Если в модуле, откомпилированном позже, имеется подпрограмма с точно такими же параметрами, то она скрывает версию из модуля, откомпилированного раньше.
Например, пусть основная программа подключает два модуля - un1 и un2:
main.pas
uses un2,un1;
procedure p(i: integer);
begin
write(1);
end;
begin
p(2.2);
p(2);
end.
un2.pas
unit un2;
procedure p(r: real);
begin
write(3);
end;
end.
un1.pas
unit un1;
procedure p(r: real);
begin
write(2);
end;
end.
В результате будет выведено 21, что означает, что первой была вызвана процедура p из модуля un1.
Поиск перегруженного имени метода осуществляется аналогично: вначале осуществляется просмотр текущего класса, затем его базового класса и т.д. до класса Object, либо до того момента, как будет встречен объект, который не может перегружать предыдущие (имя поля или свойства). Из всех найденных таким образом одноименных методов выбирается наилучший. При этом в разных классах могут быть методы с идентичными параметрами; в этом случае вызывается первый встреченный метод от данного класса к классу Object.
Подпрограммы с переменным числом параметров также участвуют в перегрузке, однако, обычные подпрограммы имеют над ними приоритет. Например, в ситуации
procedure p(i: integer);
begin
write(1);
end;
procedure p(params a: array of integer);
begin
write(2);
end;
begin
p(1)
end.
будет вызвана первая процедура.
Вызов подпрограмм из неуправляемой dll
Для вызова подпрограммы из неуправляемой dll (содержащей обычный, а не .NET-код) используется конструкция вида:
заголовок функции external 'имя dll' name 'имя функции в dll';
Например:
function MessageBox(h: integer; m,c: string; t: integer): integer;
external 'User32.dll' name 'MessageBox';
...
MessageBox(0,'Hello!','Сообщение',0);
Модули
Структура модуля
Модули предназначены для разбиения текста программы на несколько файлов. В модулях описываются переменные, константы, типы, классы, процедуры и функции. Для того чтобы эти объекты можно было использовать в вызывающем модуле (которым может быть и основная программа), следует указать имя файла модуля (без расширения .pas) в разделе uses вызывающего модуля. Файл модуля (.pas) или откомпилированный файл модуля (.pcu) должен находиться либо в том же каталоге, что и основная программа, либо в подкаталоге Lib системного каталога программы PascalABC.NET.
Модуль имеет следующую структуру:
unit имя модуля;
interface
раздел интерфейса
implementation
раздел реализации
initialization
раздел инициализации
finalization
раздел финализации
end.
Имеется также упрощенный синтаксис модулей без разделов интерфейса и реализации.
Первая строка обязательна и называется заголовком модуля. Имя модуля должно совпадать с именем файла.
Раздел интерфейса и раздел реализации модуля могут начинаться с раздела uses подключения внешних модулей и пространств имен .NET. Имена в двух разделах uses не должны пересекаться.