我花了两个小时来追踪这个错误。我可以解决它,但我不明白。
如果我有一个看起来像这样的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
ing父类时自动调用这个use
方法。
我查看了perlootut
和perlobj
并没有看到任何提及此事。
import()
是Perl中的特殊方法名称。每当你use
一个模块时,Perl会在该模块中寻找一个名为import()
的子程序,如果找到它,它将被运行。
这通常用于Exporter聪明。这意味着你的模块中有一个名为import()
的方法,你不想在加载模块时调用它是一个非常糟糕的主意。它会让你在任何时候都与Perl作战。
有关更多信息,请参阅perldoc -f import:
导入列表
没有内置的
import
功能。它只是希望将名称导出到另一个模块的模块定义(或继承)的普通方法(子例程)。use
函数调用所用包的import
方法。另见use,perlmod和Exporter。
你找到的“解决方法”也不是一个好主意。您正在从名为Foo.pm的文件中有效地加载一个名为My:Foo的模块,如果文件名和包名称不匹配,Perl将会非常困惑。
在我看来,你正在寻找这头骆驼的错误结局。你的问题不是由import
“特殊”引起的,而是由于不知道use
究竟是做什么的。根据perldoc use,use Module
与“完全相同”
BEGIN { require Module; Module->import( LIST ); }
当你使用use
时,你告诉Perl调用Module的import
方法。就那么简单。
当然,Perl是Perl,你的import
方法可能有一些方法可以确定它是否被称为use
的一部分,并且如果是这样的话会立即返回,但这只会增加不必要的复杂性。将方法重命名为更具描述性的方法(例如,import_file
,import_record
等,取决于您实际导入的内容)将是一个更好的解决方案。
import
有两种特殊方式:
除非明确给出use
一个空的导入列表(例如use Foo ();
),否则import
将在编译时作为类方法调用并传递任何导入列表参数use
。
如果import
被调用为实例或类方法(无论是由use
隐式还是显式)并且不存在这样的方法,则将返回空列表而不是抛出Can't locate object method
错误或调用AUTOLOAD。
如果它今天实施,它可能会被称为IMPORT
而不是。
所有这些也适用于unimport
(但使用no
而不是use
)。
更新:有些人已经链接到文档,其中说明use
“完全等同于”然后谎言。
它完全等同于BEGIN { require Module; Module::->VERSION(...); Module::->import(...) }
,但如果没有指定版本则省略VERSION调用,如果给出了一个明确的空列表,则省略导入调用(如后面的文档所述)。
(还要注意Module-> import(如果它存在则调用Module()函数然后在返回的任何内容上调用import方法)和Module :: - > import或'Module' - > import这是一个细微的区别。在Module类上直接调用类方法。)
import
是保留的关键字。当你use
一个模块时,将调用它的import
方法,参见the documentation。
我担心你无法改变这一点。将您的方法重命名为其他不是特殊关键字的方法。