Посмотрите программу 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
.
Для того, чтобы сделать вещи проще для вас, пакеты могут экспорт их переменные и подпрограммы в вашем основного пространства имен. Например, если я использую 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)
позволяют пакету экспортировать подпрограммы и переменные в основное пространство . @EXPORT
автоматически, без него ничего не говорит вам, импортирует подпрограммы copy
и move
в основное пространство имен хотите ли вы их или нет!
Этот последний бит очень важен. В настоящее время считается плохие манеры для использования @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
не экспортируются в вашу среду.
Действительно ли вы объявляете 'пакет Common.pm'? Это похоже на ошибку. – mob
У вас есть два пакета с тем же именем? Это может вызвать столкновение пространства имен. Всегда указывайте свои пакеты для файла, в котором они находятся (заменяя '/' '::' и зачищая '.pm'). Это также может произойти, если у вас есть * no * namespace, что на самом деле означает, что вы находитесь в 'main'. – Ether
нет - я не объявлял его Common.pm. Я просто переименовал вещи, чтобы получить пример псевдокода и опечатать. Я отредактирую. – user210757