Пакеты и модули
Область имен - namespace - часть памяти программы со своей собственной областью видимости.
Видимость переменных ограничена данным модулем .Модуль - пакет , который можно загружать и
интегрировать с данной программой .
В пакет может входить как один , так и несколько файлов-исходников .
В следующем примере создается пакет, сохраняемый как файл package1.pl:
package package1;
BEGIN { }
sub subroutine1 {print "Hello!\n";}
return 1;
END { }
Чтобы использовать в программе код пакета, надо поместить в сценарий команду require:
require 'package1.pl';
Теперь можно ссылаться на идентификаторы пакета package1, отделив его имя от идентификатора символами ::.
require 'package1.pl';
package1::subroutine1();
print $package1::variable1;
Hello!
1
Для того , чтобы не использовать префикс package1:: , нужно использовать модули .
Модуль - пакет , оформленный в виде отдельного файла с расширением .pm.
Модуль может содержать глобальные переменные .
Создадим модуль Module1
package Module1;
BEGIN {
use Exporter ();
@ISA = 'Exporter';
@EXPORT = '&subroutine1';
}
sub subroutine1 {print "Hello!\n";}
return 1;
END { }
Вызвать модуль можно так :
use Module1;
subroutine1();
Hello!
Использование команды require отличается тем , что подключение модуля происходит в момент вызова ,
в то время как команда use подключает модуль на этапе компиляции .
Имя текущего пакета можно определить с помощью встроенного идентификатора __PACKAGE__.
В следует примере имя текущего пакета выводится из подпрограммы subroutine1, входящей в пакет package1:
package package1;
BEGIN {}
sub subroutine1
{
print __PACKAGE__;
}
return 1;
END {}
Если код пакета расположен в 2-х разных файлах , можно использовать команду require несколько раз :
require 'file1.pl';
require 'file2.pl';
А можно и не вызывать 2 раза , а сделать например так :
package package1;
BEGIN {require 'package2.pl';}
sub hello {print "Hello!\n";}
return 1;
END {}
В код модуля можно встроить документацию с помощью операторов =pod и =cut :
=pod (Начало встроенной документации)
=item myTest1
Тут пошел 1-й комментарий ...
=item myTest2
Тут пошел 2-й комментарий ...
=cut (Конец встроенной документации)
Чтобы из модуля разрешить экспорт подпрограммы , но по молчанию ее не загружать , нужно использовать
@EXPORT_OK :
package Module1;
BEGIN
{
use Exporter();
@ISA = qw(Exporter);
@EXPORT_OK = qw(&subroutine1);
}
sub subroutine1 {print "Hello!\n";}
return 1;
END { }
Для вызова этой подпрограммы можно экспортировать ее явно :
# use Module1 qw{&subroutine1);
Если вы не хотите, чтобы модуль экспортировал в область глобальных имен свои имена, описанные как экспортируемые
по умолчанию, надо добавить пару круглых скобок после имени модуля, указанного в команде use:
use Module1 ();
Если вы не хотите, чтобы модуль экспортировал определенные имена, их надо перечислить во время работы с модулем Exporter
в массиве @EXPORT_FAIL :
package Uptime;
BEGIN
{
use Exporter;
@ISA = qw/Exporter/;
if ($^O ne 'MSWin32') {
@EXPORT = qw/&uptime/;
} else {
print "Sorry, no uptime available in Win32.\n";
@EXPORT_FAIL = qw/&uptime/;
}
}
sub uptime {print `uptime`;}
return 1;
END { }
Задать номер версии в коде модуля можно так :
$VERSION = 1.00;
Проверить версию модуля можно так :
use Module1();
Module1->require_version(2.00);
Если в программе вызывается несуществующая процедура из какого-то модуля , это можно обработать
с помощью AUTOLOAD :
package Autoload;
BEGIN {
use Exporter ();
@ISA = qw(Exporter);
@EXPORT = qw(&AUTOLOAD);
}
sub AUTOLOAD () {
my $subroutine = $AUTOLOAD;
$subroutine =~ s/.*:://;
print "You called $subroutine with these arguments: ",
join(", ", @_);
}
return 1;
END { }
Следующий фрагмент показывает , что произойдет , если вызвать несуществующую подпрограмму :
use Autoload;
printem (1, 2, 3);
Вывод будет такой :
You called printem with these arguments: 1, 2, 3
Для каждого модуля можно определить свою собственную AUTOLOAD .
Для выборочной загрузки отдельных частей модуля существует стандартный модуль AutoLoader :
Для этого в модуле перед подпрограммами нужно поместить ключевое слово __END__ ,
а затем из командной строки обработать исходный файл модуля командой
perl -w -e 'use AutoSplit; autosplit("%1", "%2")'
где первый параметр - имя модуля , второй - каталог , где будет записан результат .
Исходный код будет разбит на отдельные файлы с расширением .al .
Чтобы модуль мог использовать механизм автозагрузки файлов, созданных с помощью autosplit,
его главая часть должна быть организована специальным образом.
Примером может служить модуль POSIX, который разбивает свои многочисленные подпрограммы на отдельные файлы
и загружает их только тогда, когда они действительно требуются пользователю:
package POSIX;
use AutoLoader;
......
sub AUTOLOAD
{
$AutoLoader::AUTOLOAD = $AUTOLOAD;
goto &Autoloader::AUTOLOAD;
}
|
|