Exporter

定义一个import()方法最常见的办法是从Exporter模块继承下来。Exporter是一个核心模块,也是Perl语言中成为事实标准的核心功能。在Exporter的import()实现中,你传入的参数列表将被认为是子程序名字的列表,当一个子程序被import(),它在当前包和原来所在的包里就都可以被使用了。

用一个例子最能帮助理解这个概念。Caterpillar.pm的内容如下:

  1. use strict;
  2. use warnings;
  3. package Caterpillar;
  4. # 继承自Exporter
  5. use parent ("Exporter");
  6. sub crawl { print "inch inch"; }
  7. sub eat { print "chomp chomp"; }
  8. sub pupate { print "bloop bloop"; }
  9. our @EXPORT_OK = ("crawl", "eat");
  10. return 1;

包变量@EXPORT_OK应该包含子程序名字的列表。

另一块代码就可以通过名字来import()这些子程序,一般使用use语句:

  1. use strict;
  2. use warnings;
  3. use Caterpillar ("crawl");
  4. crawl(); # "inch inch"

在这种情况下,当前包是main所以crawl()实际上是调用了main::crawl(),(因为被导入了)映射到Caterpillar::crawl()

注意:不管@EXPORT_OK的内容是什么,通过“常规写法”使用这些函数总是可以的:

  1. use strict;
  2. use warnings;
  3. use Caterpillar (); # 没有提供任何子程序名,import()不会被调用
  4. # 然而……
  5. Caterpillar::crawl(); # "inch inch"
  6. Caterpillar::eat(); # "chomp chomp"
  7. Caterpillar::pupate(); # "bloop bloop"

Perl没有私有方法,习惯上在希望私有的方法名前面有一个或者两个下划线。

@EXPORT

Exporter模块还定义了一个包变量叫@EXPORT,也包含一组子程序名。

  1. use strict;
  2. use warnings;
  3. package Caterpillar;
  4. # 继承自Exporter
  5. use parent ("Exporter");
  6. sub crawl { print "inch inch"; }
  7. sub eat { print "chomp chomp"; }
  8. sub pupate { print "bloop bloop"; }
  9. our @EXPORT = ("crawl", "eat", "pupate");
  10. return 1;

如果没有给import()传入任何参数,@EXPORT中写出的子程序将全部被导出,就像这样:

  1. use strict;
  2. use warnings;
  3. use Caterpillar; # 调用import()但不提供参数
  4. crawl(); # "inch inch"
  5. eat(); # "chomp chomp"
  6. pupate(); # "bloop bloop"

不过我们又回到了那种情况,没有其他提示的话,我们很难知道crawl()原先是在哪儿定义的。这件事情有两个寓意:

  1. 当我们用Exporter创建模块的时候,不要用@EXPORT来导出子程序,总是让调用者以“常规方法”调用子程序,或者显式地import()它们(使用比如:use Caterpillar ("crawl")提供了一条很强的线索,告诉我们可以从Caterpillar.pm中找到crawl()的定义)。

  2. use一个使用Exporter的模块时,总是显式写明你希望import()的子程序,如果你不想import()任何子程序,而是用常规方法引用它们,你必须显式提供一个空的列表:use Caterpillar ()