考虑以下脚本p.pl
:
use strict;
use warnings;
use AA;
BB::bfunc();
文件AA.pm
是:
package AA;
use BB;
1;
,文件BB.pm
为:
package BB;
sub bfunc {
print "Running bfunc..\n";
}
1;
运行p.pl
会输出(没有警告或错误):
Running bfunc..
问:即使BB::bfunc()
中没有p.pl
,为什么可以从use BB;
致电p.pl
?这个奇怪的行为不是吗?或者是否存在可能有用的情况?
(对我来说,似乎这种行为只会向另一个软件包泄露信息并违反数据隐藏原则。导致难以维护的程序..)
答案 0 :(得分:3)
虽然最好是use
或require
您计划访问的每个依赖项(试图避免在此处使用),但您不必这样做
只要您使用完整的包名称,就可以了。重要的是Perl知道名称空间。如果没有,它将失败。
当你use
时,这相当于:
BEGIN {
require Foo::Bar;
Foo::Bar->import();
}
require
将使用Foo::Bar
并根据操作系统的约定将其转换为路径。在Linux上,它会尝试在Foo/Bar.pm
内的某处找到@INC
。然后它将加载该文件并在%INC
中记下它加载文件。
现在Perl知道该命名空间。如果是use
,它可能会import
进入您自己的命名空间。但只要你使用全名,它就会随时随地可用。同样地,您在主script.pl
中拥有的内容可以通过说main::frobnicate()
在包内找到。 (请不要那样做!)
在一个.pm
模块文件中捆绑多个名称空间/包也并不罕见。 CPAN上有很多大牌,就像XML::Twig一样。
如果你这样做,并且不导入任何东西,获取不同名称空间下的东西的唯一方法是使用全名。
如您所见,这根本不是污染。
答案 1 :(得分:3)
您没有污染命名空间,因为BB
中的函数未被“导入”到您现有的命名空间中。
它们是分开的,可以自主引用。
如果您正在制作模块,那么通常您会通过Exporter
两个列表进行定义:
@EXPORT
和@EXPORT_OK
。
前者是您use
包时应导入的内容列表。后者是您可以通过以下方式明确导入的内容:
use MyPackage qw ( some_func );
您还可以通过package
在本地命名空间中定义our
个变量,并通过$main
引用它们。
our $fish = "haddock";
print $main::fish;
执行此操作时,您将明确引用main
命名空间。当您use
某个模块时,您需要perl
去寻找它,并将其包含在%INC
中。然后我'知道'那个命名空间 - 因为它必须为了解决依赖关系。
但这不是名称空间污染,因为在您提出要求之前,它不会在您的命名空间中包含任何内容。
如果在同一程序中有多个包,这可能会更有意义:
use strict;
use warnings;
package CC;
our $package_var = "Blong";
sub do_something {
print $package_var,"\n";
}
package main;
use Data::Dumper;
our $package_var = "flonk";
print Dumper $package_var;
print Dumper $CC::package_var;
每个package
都是它自己的命名空间,但是你可以在另一个中“捅”东西。 perl
也可以通过对象实现这一点 - 实例化对象的内部或实际上“修补”它们。
这是非常强大的,但我通常建议真的不好的风格。