避免与具有相同方法名称的模块发生冲突

时间:2014-12-10 00:53:23

标签: perl perl-module

我正在考虑使用Cpan中的以下perl模块:

CSS-Minifier
Javascript-Minifier

我从文档中注意到我需要调用" minify"两种方法。
我知道我必须错过像Perl新手这样明显的东西,但是他们不会碰撞吗?

我想问题是如何指定" minify"单独为每个模块,以便CSS模块只在CSS上工作,JS模块只在JS上工作?

3 个答案:

答案 0 :(得分:5)

Perl模块包括子程序。通常,使用模块的原因是使用该模块中的子例程。模块将具有自己的包名称,该模块中的子例程将存在于该包中。所以一个简单的模块可能如下所示:

package MyModule;

sub my_sub {
  print "This is my sub\n";
}

如果我在我的代码中加载该模块,那么我必须使用其完全限定名称(即包括包名称)来调用子例程。

use MyModule;

MyModule::my_sub();

这很快就会重复,所以很多模块会将导出他们的子程序放到你的包中。他们使用名为@EXPORT@EXPORT_OK的特殊数组执行此操作。

如果我将子程序的名称放入@EXPORT,那么无论何时使用该模块,它都会自动导入。

package MyModule;

our @EXPORT = ('my_sub');

sub my_sub {
  print "This is my sub\n";
}

然后我可以这样使用它:

use MyModule;

my_sub();

或者,我可以使用定义可选导出的@EXPORT_OK。用户可以要求导入@EXPORT_OK中的子例程 - 但这不会自动发生。您要求通过在use语句中包含该名称来导入选项导出。

package MyModule;

our @EXPORT_OK = ('my_sub');

sub my_sub {
  print "This is my sub\n";
}

我现在可以这样做:

use MyModule ('my_sub');

my_sub();

还有一个可能有用的技巧。您可以在use语句中使用空列表关闭自动导入。假设我们有模块的@EXPORT版本:

use MyModule (); # Turn off imports

my_sub(); # Doesn't work
MyModule::my_sub(); # works

现在我们拥有了解您的具体问题所需的知识。最简单的解决方案是关闭所有自动导入并使用两个子例程的完全限定名称。

use CSS::Minifier ();
use JavaScript::Minifier();

CSS::Minifier::minify();
JavaScript::Minifier::minify();

但我们可以有点聪明。两个模块的文档都表明两个导入都是可选的,因此您需要显式导入子例程。

use CSS::Minifier ('minify');
use JavaScript::Minifier('minify');

这显然是一件坏事,因为你不能导入两个同名的子程序!

但是,查看模块的源代码,我发现JavaScript :: Minifier的文档是错误的(编辑:submitted a report关于此错误)。 CSS :: Minifier有这行代码:

our @EXPORT_OK = qw(minify);

但是JavaScript :: Minifier有这个:

our @EXPORT = qw(minify);

因此,导出是从JavaScript :: Minifier自动导出的,CSS :: Minifier是可选的。所以最简单的方法是:

use JavaScript::Minifier; # Automatically imports minify
use CSS::Minifier; # Doesn't import option export minify

然后你可以使用这两个子程序:

minify(); # Automatic export from JavaScript::Minifier
CSS::Minifier::minify(); # Fully-qualified name from CSS::Minifier
但是,我怀疑这是一个糟糕的方法,因为很难确定minify()的不合格版本来自哪里。因此,我建议关闭两个模块的所有导入,并使用两个子程序的完全限定名称。

答案 1 :(得分:2)

如果同时exported同时调用它,请使用:

CSS::Minifier::minify();

JavaScript::Minifier::minify();

答案 2 :(得分:1)

您可以使用完全限定名称来引用子例程并消除歧义。并使用别名创建较短的名称。

use CSS::Minifier;
use JavaScript::Minifier;

BEGIN {
   *minify_css = \&{CSS::Minifier::minify};
   *minify_js  = \&{JavaScript::Minifier::minify};
}

minify_css(...);
minify_js(...);