perl import子例程有什么特别之处?

时间:2017-11-03 13:19:58

标签: perl packages

我花了两个小时来追踪这个错误。我可以解决它,但我不明白。

如果我有一个perl模块./lib/My/Foo.pm,如下所示:

package My::Foo;

sub import {print "importing\n"}

1;

然后使用它隐式调用import子例程:

$ PERL5LIB=./lib perl -MMy::Foo -e 'print "ok\n"'
importing
ok

但是如果我复制相同的模块并在没有冒号的情况下使用它,则import子例程被调用。

$ cp lib/My/Foo.pm lib/Foo.pm
$ PERL5LIB=./lib perl -MFoo -e 'print "ok\n"'
ok

如果我将import更改为do_import之类的其他内容,则不会调用子例程。所以我可以避免这种行为。但在我的实际用例中,我有一个Import类和一个抽象方法import,然后在子类中实现该方法。所以我希望在import父类时自动调用这个use方法。

我查看perlootutperlobj并没有看到任何提及此事。

4 个答案:

答案 0 :(得分:7)

import()是Perl中的特殊方法名称。每当你use一个模块时,Perl会在该模块中寻找一个名为import()的子程序,如果找到它,它将被运行。

这最常用于Exporter聪明。这意味着你的模块中有一个名为import()的方法,你不想在加载模块时调用它是一个非常糟糕的主意。它会让你在任何时候都与Perl作战。

有关详细信息,请参阅perldoc -f import

  

导入列表

     

没有内置import功能。它只是希望将名称导出到另一个模块的模块定义(或继承)的普通方法(子例程) use函数调用所用包的import方法。另请参阅useperlmodExporter

您找到的“解决方法”也不是一个好主意。您正在从名为Foo.pm的文件中有效地加载名为My:Foo的模块,如果文件名和包名称不匹配,Perl将会非常困惑。

答案 1 :(得分:6)

在我看来,你正在看这头骆驼的错误结局。您的问题不是由import“特殊”引起的,而是由于不知道use究竟是做什么的。根据{{​​3}},use Module

完全相同
BEGIN { require Module; Module->import( LIST ); }

当您使用use时,您告诉Perl调用模块的import方法。简单。

当然,Perl是Perl,你的import方法可能有一些方法可以判断它是否被作为use的一部分被调用,并且如果是这样的话会立即返回,但那会只是添加不必要的复杂性。将方法重命名为更具描述性的内容(例如,import_fileimport_record等,具体取决于您实际导入的内容)将是一个更好的解决方案。

答案 2 :(得分:3)

import是保留关键字。当您use模块时,将调用其import方法,请参阅the documentation

我担心你无法改变这一点。将您的方法重命名为非特殊关键字的其他内容。

答案 3 :(得分:3)

import在两个方面很特别:

除非明确给出use空导入列表(例如use Foo ();),否则{}将在编译时作为类方法调用import并传递任何导入列表参数{{1}给了。

如果将use作为实例或类方法(无论是import隐式显式)还是显式调用,并且不存在此类方法,则会返回空列表而不是use错误被抛出或被调用AUTOLOAD。

如果它今天实施,可能会被称为Can't locate object method

以上所有内容也适用于IMPORT(但使用unimport代替no)。

更新:有些链接到文档,其中显示use与“完全等效”,然后谎言。

它完全等同于use,但如果未指定版本则省略VERSION调用,并且如果给出明确的空列表,则省略导入调用(如稍后的文档所述)。

(另请注意Module-> import之间的细微区别(如果存在则调用Module()函数,然后在返回的任何内容上调用import方法)和Module :: - > import或'Module'- > import是Module类上直接的类方法调用。)