看看程序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 的引用。这些是File::Find 命名空间下File/Find.pm 包内的变量$name 和$dir。
为了方便您,包可以导出它们的变量和子例程到您的 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 );
不好玩。
像这样:
use MyCommonPkg qw(foo bar);
在这种情况下,仅导出子例程 foo 和 bar。子例程 thisSubroutineIsNotDefinedAnywhereElse 和 barfoo 不会导出到您的环境中。