我花了两个小时来追踪这个错误。我可以解决它,但我不明白。
如果我有一个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
方法。
我查看perlootut
和perlobj
并没有看到任何提及此事。
答案 0 :(得分:7)
import()
是Perl中的特殊方法名称。每当你use
一个模块时,Perl会在该模块中寻找一个名为import()
的子程序,如果找到它,它将被运行。
这最常用于Exporter聪明。这意味着你的模块中有一个名为import()
的方法,你不想在加载模块时调用它是一个非常糟糕的主意。它会让你在任何时候都与Perl作战。
有关详细信息,请参阅perldoc -f import:
导入列表
没有内置
import
功能。它只是希望将名称导出到另一个模块的模块定义(或继承)的普通方法(子例程)。use
函数调用所用包的import
方法。另请参阅use,perlmod和Exporter。
您找到的“解决方法”也不是一个好主意。您正在从名为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_file
,import_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类上直接的类方法调用。)