Пакеты
Конструктор и деструктор пакета ВEGIN и END
Конструктором в объектно-ориентированном программировании называется специальная подпрограмма, предназначенная для создания объекта. Деструктором называется подпрограмма, вызываемая для выполнения завершающих действий, связанных с ликвидацией объекта: закрытие файлов, вывод сообщений и т. д.
Для создания пакета, как мы знаем, требуется только его объявление (в том числе, предполагаемое по умолчанию объявление package main). Вместе с тем, существуют специальные подпрограммы, выполняющие функции инициализации и завершения пакета. По аналогии их можно назвать конструкторами и деструкторами пакета, хотя никаких пакетов они не создают и не удаляют. Это подпрограммы BEGIN и END. При описании этих подпрограмм ключевое слово sub, необходимое при объявлении обычной подпрограммы, можно опустить. Таким образом, /синтаксис, подпрограмм BEGIN, END имеет вид:
BEGIN (block) END {block}
Подпрограмма BEGIN выполняется сразу после своего определения до завершения компиляции оставшейся части программы. Попробуйте запустить интерпретатор peri в интерактивном режиме. Если ему передать строку:
print "Привет!";
…то он напечатает ее только после того, как обнаружит во входном потоке признак конца файла (например, комбинацию CTRL + D). Если же в интерактивном режиме определить конструктор пакета:
BEGIN {print "Привет!"};
…то вывод строки "Привет!" будет осуществлен немедленно. Это свойство конструктора можно использовать, чтобы в начале пакета определять или импортировать имена из других пакетов. Затем эти имена будут влиять на процесс компиляции оставшейся части пакета.
Можно определить несколько блоков BEGIN внутри файла, они будут выполняться один за другим в порядке определения.
Подпрограмма END выполняется настолько поздно, насколько это возможно, т. е. при завершении работы интерпретатора. Можно указать несколько блоков END, при этом они будут выполняться в порядке, обратном определению.
END { print "Завершаем работу, до свидания\п"; }.. BEGIN { print "Привет, начинаем работу\n"; } print "Это тело программы\n"; BEGIN { print "Еще один блок BEGIN после блока END\n"; }
Здесь сознательно выбран не совсем естественный порядок следования конструкторов и деструкторов BEGIN и END в тексте программы, чтобы подчеркнуть, в каком порядке они будут вызываться. Вывод выглядит так:
Привет, начинаем работу Еще один блок BEGIN после блока END Это тело программы Завершаем работу, до свидания
Автозагрузка
При попытке обратиться к функции из некоторого пакета, которая в нем не определена, интерпретатор завершает работу с выдачей сообщения об ошибке. Если же в этом пакете определить функцию с именем AUTOLOAD, то при вызове из пакета несуществующей функции вместо нее будет вызвана функция AUTOLOAD с параметрами, переданными при вызове несуществующей функции. При этом интерпретатор peri продолжает выполнение программы. Полное имя несуществующей функции с указанием имени пакета сохраняется в переменной $AUTOLOAD из того же пакета, что и функция AUTOLOAD. Например, для основного пакета main можно определить функцию AUTOLOAD, как в следующем примере.
#!/usr/bin/perl sub AUTOLOAD { print "Функция $AUTOLOAD не определена\п"; } print "Начало работы\п"; f(); print "Конец работы\n";
Функция f (), в отличие от функции AUTOLOAD, не определена в пакете main, поэтому в результате выполнения данной программы будут выведены сообщения:
Начало работы Функция main::f не определена Конец работы
Этот пример достаточно тривиальный, но он дает представление об использовании функции AUTOLOAD. В состав дистрибутива Perl входят стандартные модули, многие из которых содержат собственные, достаточно сложные определения функции AUTOLOAD, которые можно рассмотреть в качестве более сложного примера.