【问题标题】:Perl: when to use Export in modules?Perl:何时在模块中使用导出?
【发布时间】:2014-02-10 13:59:21
【问题描述】:

我对这些线条感到困惑

use Exporter;
our @EXPORT =qw(a b);

在一个包中。

我见过不使用@EXPORT 的包,而且工作得很好。很困惑...我用谷歌搜索,但没有找到太多解释。

我的问题是什么时候应该使用@EXPORT?不使用的原因是什么?

【问题讨论】:

  • 当你想将某些东西导出到调用者的命名空间中时(并且当你不使用像 Sub::Exporter 这样更新更好的东西时)。
  • 你的例子有@EXPORT双引号的内容。使用 qw(a b) 或使用 ('a','b')。
  • @harmic,是的,修改了它。
  • a 和 b 之间还有一个逗号。您最终会得到一个名为 a,b 的条目(qw 不需要逗号)

标签: perl perl-module


【解决方案1】:

实际上有两个问题(或者您可能只问一个,但完整的答案必须同时回答两个问题)。

什么时候需要使用 Exporter

当您“使用”某人的 perl 模块时,会执行两个不同的操作。首先是加载他们的包;第二个是调用他们包的'import' sub。

仅仅加载他们的包会导致他们包的内容被定义在他们包的命名空间中。您可以直接使用它,而无需第二步,但您必须使用完整的包名称来引用它的所有子组件等。例如,如果他们的包裹包含:

package Foo::Bar;

sub fabronicate {
    print "This is a nice sub!\n";
}

那么任何想要使用 if 的人都必须这样做:

use Foo::Bar;

Foo::Bar::fabronicate();

所有在前面输入 Foo::Bar 的东西都会很快变老。对此的解决方案是在包中声明一个“导入”子。该子将负责将公共子(以及变量和模块应提供的任何其他内容)导出到调用者的命名空间(“使用”模块的包)。

Exporter 模块的作用是为您提供一个“导入”子模块。这意味着您不必编写一些看起来很奇怪的代码来为要导出的所有符号创建别名,这一切都为您完成。

请注意,您不必使用 Exporter。您可以编写自己的导入例程,或者有其他模块来处理导出符号。

或者你可以让使用你的模块的人一直明确地提到包名。这在面向对象的模块中很常见,因为只有类方法(例如构造函数)需要显式地以包名称为前缀。拥有对象实例后,包查找是自动的。例如:

my $o = Foo::Bar->new();
$o->fabronicate();

什么时候需要使用@EXPORT

Exporter 模块需要知道包中定义的符号(子、变量等),哪些应该被导出。通常只会导出一小部分。它会参考一些包变量来找出答案:@EXPORT 和 @EXPORT_OK。

@EXPORT 包含您希望导出给使用您的模块的任何人的符号列表,它们没有明确提及要导入的符号列表。最初这听起来不错,直到您意识到如果您的模块正在导出一些名称,而这些名称也被其他模块导出,则会出现问题。

@EXPORT_OK 包含可以导出的符号列表,如果调用模块特别请求它们。调用模块在“use”语句中使用模块名称后的名称列表来指定这些。

use Foo::Bar qw(fabronicate);

# Now I can call fabronicate directly!

请注意,提供符号列表两种方式都可以:@EXPORT 和 @EXPORT_OK 之间的最大区别在于,当有人使用您的模块但未提供任何列表时会发生什么,如下所示:

use Foo::Bar;

在这种情况下,@EXPORT 中定义的所有内容都会被导入,@EXPORT_OK 中定义的任何内容都不会被导入。

还有一些其他变量允许您指定导入多个符号的标签。 Exporter 文档是查找此内容的最佳位置。

【讨论】:

  • 感谢您的解释!一个问题,如果你使用@EXPORT,你也可以在调用脚本中指定导入哪些方法,对吗?喜欢使用 Foo::Bar qw(fabronicate);
  • @user2157668 正确。我已经更新了答案以使其更清楚。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-12-09
  • 2011-11-06
  • 2014-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多