我花了两个小时找出这个错误。我可以解决它,但我不明白它。
如果我有一个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
,然后在子类中实现这个方法。所以我 * 不 * 希望在use
调用父类时自动调用这个import
方法。
我查看了perlootut
和perlobj
,没有看到任何提到这一点。
4条答案
按热度按时间rxztt3cl1#
import()
是Perl中的一个特殊方法名。每当您对一个模块执行use
操作时,Perl都会在该模块中查找一个名为import()
的子例程,如果找到了,它就会运行。这是Exporter最常用的技巧。这意味着在模块中有一个名为
import()
的方法,而您不希望在加载模块时被调用,这是一个非常糟糕的主意。它会让您在每个回合都与Perl战斗。请参阅perldoc -f import以取得更多信息:
导入列表
没有内置的
import
函数。它只是一个普通的方法(子例程),由希望将名称导出 * 到另一个模块的模块定义(或继承)。use
函数调用所用包的import
方法 *。另请参阅use、perlmod和Exporter。您找到的“变通方法”也不是一个很好的主意。您实际上是从一个名为www.example.com的文件中加载一个名为My:Foo的模块Foo.pm如果文件名和包名不匹配,Perl会感到非常困惑。
qni6mghb2#
在我看来,您似乎看错了 Camel 的一头。您的问题不是由于
import
“特殊”而引起的,而是由于不知道use
实际上是做什么的。根据perldoc use,use Module
“完全等价于”当您使用
use
时,* 您是在告诉Perl调用Module的import
方法。* 就这么简单。当然,Perl就是Perl,
import
方法可能有某种方法来判断它是否作为use
的一部分被调用,如果是这样的话,就立即返回,但这只会增加不必要的复杂性。(例如,import_file
、import_record
等,取决于您实际导入的内容)将是一个更好的解决方案。camsedfj3#
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调用;如果给出了明确的空列表,则省略import调用(如后面的文档所述)。(Also注意Module-〉import(如果存在,则调用Module()函数,然后对返回的任何内容调用import方法)与Module::-〉import或'Module'-〉import(对Module类的直接类方法调用)之间的细微区别。
8ljdwjyq4#
import
是一个保留的关键字。当你use
一个模块时,它的import
方法将被调用,参见the documentation。恐怕你不能改变它。把你的方法重命名为其他的不是特殊关键字的东西。