Взгляните на программу package MyCommonPkg.pm
и посмотрите, что в ней написано. Есть ли что-то подобное?
package MyCommonPkg;
use Exporter qw(import); # Might be "require" and not "use"
our @EXPORT = qw(thisSubroutineIsNotDefinedAnywhereElse);
Синтаксис может быть немного другим. Главное, что вы должны увидеть, это утверждение package
, что оно использует Exporter
и что в массиве @EXPORT
есть имя вашей подпрограммы.
Происходит конфликт пространства имен. Ваш пакет определяет ту же подпрограмму, которую вы определяете.
Чтобы этого не произошло, Perl использует пространства имен . По умолчанию ваше пространство имен main
. Однако предполагается, что пакеты определяют свои собственные однофамильцы с помощью команды package
.
Полное пространство имен подпрограммы или переменной - это пространство имен, за которым следует двоеточие, за которым следует подпрограмма или имя переменной. Например, если вы посмотрите на File :: Find , вы увидите ссылки на переменные $File::Find::name
и $File::Find::dir
. Это переменные $name
и $dir
внутри пакета File/Find.pm
в пространстве имен File::Find
.
Чтобы вам было проще, пакеты могут экспортировать свои переменные и подпрограммы в ваше пространство имен main . Например, если я использую File :: Copy , O может сделать это:
...
use File::Copy
...
copy ($file, $to_dir);
Вместо:
...
use File::Copy
...
File::Copy::copy ($file, $to_dir);
Если вы посмотрите на File/Copy.pm
, вы увидите следующее:
package File::Copy;
...
our(@ISA, @EXPORT, @EXPORT_OK, $VERSION, $Too_Big, $Syscopy_is_copy);
...
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(copy move);
package File::Copy;
определяет пространство имен. require Exporter;
и @ISA = qw(Exporter)
позволяют пакету экспортировать подпрограммы и переменные в пространство имен main . @EXPORT
автоматически, ничего не сообщая, импортирует подпрограммы copy
и move
в пространство имен main независимо от того, хотите вы их или нет!
Этот последний бит очень важен. В настоящее время считается плохими манерами для использования @EXPORT
. Вместо этого вы должны использовать @EXPORT_OK
, что требует от вас перечислить подпрограммы, которые вы хотите использовать. Более современные пакеты, такие как Scalar :: Util , делают это.
Итак, несколько вещей. Во-первых, есть ли у вашего MyCommonPkg
оператор package MyCommonPkg;
. Если нет, то должно. Это предотвращает негативное влияние подпрограмм и переменных пакетов на вашу программу. Затем вы можете использовать @EXPORT
или @EXPORT_OK
.
Если MyCommonPkg
имеет оператор package
, использует ли он @EXPORT
? Если это так, у вас есть несколько способов избежать этой проблемы:
- Игнорировать предупреждение. Это просто предупреждение. Поскольку вы знаете, что переопределяете подпрограмму и хотите использовать свое определение подпрограммы, игнорируйте ее.
Вы можете сделать это, чтобы отключить предупреждение при переопределении подпрограммы:
use MyCommonPkg;
no warnings qw(redefine);
sub thisSubroutineIsNotDefinedAnywhereElse {
...
}
use warnings qw(redefine);
- Используйте
require MyCommonPkg;
вместо use MyCommonPkg;
. Это предотвратит импорт любых подпрограмм или переменных в ваше пространство имен, включая те, которые вы хотели использовать. Допустим, MyCommonPkg
определяет четыре подпрограммы: thisSubroutineIsNotDefinedAnywhereElse
, foo
, bar
и barfoo
. Чтобы использовать любую из этих подпрограмм.
Вам нужно сделать это:
my $answer = MyCommonPkg::foo( $input );
Не весело.
Используйте другое имя для вашей подпрограммы. Должно быть задокументировано, что эта подпрограмма определена в MyCommonPkg
, и если вы хотите использовать MyCommonPkg
, вы не должны использовать имена подпрограмм, которые экспортируются.
Наконец, если MyCommonPkg
является довольно новым и не используется в десятках программ, используйте @EXPORT_OK
вместо @EXPORT
и убедитесь, что все программы, использующие MyCommonPkg
, изменены на экспортируйте нужные им подпрограммы:
Вот так:
use MyCommonPkg qw(foo bar);
В этом случае экспортируются только подпрограммы foo
и bar
. Подпрограммы thisSubroutineIsNotDefinedAnywhereElse
и barfoo
не экспортируются в вашу среду.