Exporter
定义一个import()
方法最常见的办法是从Exporter模块继承下来。Exporter是一个核心模块,也是Perl语言中成为事实标准的核心功能。在Exporter的import()
实现中,你传入的参数列表将被认为是子程序名字的列表,当一个子程序被import()
,它在当前包和原来所在的包里就都可以被使用了。
用一个例子最能帮助理解这个概念。Caterpillar.pm
的内容如下:
use strict;
use warnings;
package Caterpillar;
# 继承自Exporter
use parent ("Exporter");
sub crawl { print "inch inch"; }
sub eat { print "chomp chomp"; }
sub pupate { print "bloop bloop"; }
our @EXPORT_OK = ("crawl", "eat");
return 1;
包变量@EXPORT_OK
应该包含子程序名字的列表。
另一块代码就可以通过名字来import()
这些子程序,一般使用use
语句:
use strict;
use warnings;
use Caterpillar ("crawl");
crawl(); # "inch inch"
在这种情况下,当前包是main
所以crawl()
实际上是调用了main::crawl()
,(因为被导入了)映射到Caterpillar::crawl()
。
注意:不管@EXPORT_OK
的内容是什么,通过“常规写法”使用这些函数总是可以的:
use strict;
use warnings;
use Caterpillar (); # 没有提供任何子程序名,import()不会被调用
# 然而……
Caterpillar::crawl(); # "inch inch"
Caterpillar::eat(); # "chomp chomp"
Caterpillar::pupate(); # "bloop bloop"
Perl没有私有方法,习惯上在希望私有的方法名前面有一个或者两个下划线。
@EXPORT
Exporter模块还定义了一个包变量叫@EXPORT
,也包含一组子程序名。
use strict;
use warnings;
package Caterpillar;
# 继承自Exporter
use parent ("Exporter");
sub crawl { print "inch inch"; }
sub eat { print "chomp chomp"; }
sub pupate { print "bloop bloop"; }
our @EXPORT = ("crawl", "eat", "pupate");
return 1;
如果没有给import()
传入任何参数,@EXPORT
中写出的子程序将全部被导出,就像这样:
use strict;
use warnings;
use Caterpillar; # 调用import()但不提供参数
crawl(); # "inch inch"
eat(); # "chomp chomp"
pupate(); # "bloop bloop"
不过我们又回到了那种情况,没有其他提示的话,我们很难知道crawl()
原先是在哪儿定义的。这件事情有两个寓意:
当我们用Exporter创建模块的时候,不要用
@EXPORT
来导出子程序,总是让调用者以“常规方法”调用子程序,或者显式地import()
它们(使用比如:use Caterpillar ("crawl")
提供了一条很强的线索,告诉我们可以从Caterpillar.pm
中找到crawl()
的定义)。当
use
一个使用Exporter的模块时,总是显式写明你希望import()
的子程序,如果你不想import()
任何子程序,而是用常规方法引用它们,你必须显式提供一个空的列表:use Caterpillar ()
。