perl import 子例程有什么特别之处?
What is special about the perl import subroutine?
我花了两个小时才找到这个错误。我可以解决它,但我不明白它。
如果我有一个看起来像这样的 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
class 和一个抽象方法 import
,然后在 subclasses 中实现该方法。所以我不希望这个import
方法在use
父class时自动调用class。
我查看了 perlootut
和 perlobj
,但没有看到任何提及。
import
是保留关键字。当你 use
一个模块时,它的 import
方法将被调用,见 the documentation.
恐怕你无法改变这一点。将您的方法重命名为不是特殊关键字的其他名称。
import()
是 Perl 中的特殊方法名。每当您 use
一个模块时,Perl 都会在该模块中寻找一个名为 import()
的子例程,如果找到它,它将是 运行.
这最常用于 Exporter 聪明。这意味着在您的模块中有一个名为 import()
的方法,您不想在加载模块时调用它是一个 非常糟糕的主意 。它会让你动不动就和 Perl 战斗。
有关更多信息的指针,请参阅 perldoc -f import:
import LIST
There is no builtin import
function. It is just an ordinary method (subroutine) defined (or inherited) by modules that wish to export names to another module. The use
function calls the import
method for the package used. See also use, perlmod, and Exporter.
您发现的 "workaround" 也不是一个很好的主意。您实际上是从一个名为 Foo.pm 的文件中加载一个名为 My:Foo 的模块,如果文件名和包名不匹配,Perl 会感到非常困惑。
在我看来,您看错了这头骆驼。您的问题不是由 import
成为 "special" 引起的,而是由于不知道 use
究竟做了什么。根据 perldoc use,use Module
是 "exactly equivalent" 到
BEGIN { require Module; Module->import( LIST ); }
当您使用 use
时,您是在告诉 Perl 调用模块的 import
方法。 就这么简单。
当然,Perl 就是 Perl,您的 import
方法可能有一些方法可以确定它是否作为 use
的一部分被调用,如果是,则立即 return这种情况,但这只会增加不必要的复杂性。将方法重命名为更具描述性的名称(例如 import_file
、import_record
等,具体取决于您实际导入的内容)将是更好的解决方案。
import
有两个特殊之处:
除非 use
明确给出一个空导入列表(例如 use Foo ();
),否则 import
将在编译时作为 class 方法调用并传递任何导入已给出列表参数 use
。
如果 import
作为实例或 class 方法调用(无论是 use
隐式调用还是显式调用)并且不存在此类方法,将返回空列表而不是Can't locate object method
抛出错误或调用 AUTOLOAD。
如果今天实施,它可能会被称为 IMPORT
。
以上所有内容也适用于 unimport
(但使用 no
而不是 use
)。
更新:有些链接到文档,其中说 use
是 "exactly equivalent" 然后是谎言。
它完全等同于 BEGIN { require Module; Module::->VERSION(...); Module::->import(...) }
,只是如果没有指定版本则省略 VERSION 调用,如果给出明确的空列表则省略 import 调用(正如文档稍后阐明的那样)。
(另请注意 Module->import(如果存在则调用 Module() 函数,然后在任何 returns 上调用 import 方法)和 Module::->import 或'Module'->import 这是对模块 class 的直接 class 方法调用。)
我花了两个小时才找到这个错误。我可以解决它,但我不明白它。
如果我有一个看起来像这样的 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
class 和一个抽象方法 import
,然后在 subclasses 中实现该方法。所以我不希望这个import
方法在use
父class时自动调用class。
我查看了 perlootut
和 perlobj
,但没有看到任何提及。
import
是保留关键字。当你 use
一个模块时,它的 import
方法将被调用,见 the documentation.
恐怕你无法改变这一点。将您的方法重命名为不是特殊关键字的其他名称。
import()
是 Perl 中的特殊方法名。每当您 use
一个模块时,Perl 都会在该模块中寻找一个名为 import()
的子例程,如果找到它,它将是 运行.
这最常用于 Exporter 聪明。这意味着在您的模块中有一个名为 import()
的方法,您不想在加载模块时调用它是一个 非常糟糕的主意 。它会让你动不动就和 Perl 战斗。
有关更多信息的指针,请参阅 perldoc -f import:
import LIST
There is no builtin
import
function. It is just an ordinary method (subroutine) defined (or inherited) by modules that wish to export names to another module. Theuse
function calls theimport
method for the package used. See also use, perlmod, and Exporter.
您发现的 "workaround" 也不是一个很好的主意。您实际上是从一个名为 Foo.pm 的文件中加载一个名为 My:Foo 的模块,如果文件名和包名不匹配,Perl 会感到非常困惑。
在我看来,您看错了这头骆驼。您的问题不是由 import
成为 "special" 引起的,而是由于不知道 use
究竟做了什么。根据 perldoc use,use Module
是 "exactly equivalent" 到
BEGIN { require Module; Module->import( LIST ); }
当您使用 use
时,您是在告诉 Perl 调用模块的 import
方法。 就这么简单。
当然,Perl 就是 Perl,您的 import
方法可能有一些方法可以确定它是否作为 use
的一部分被调用,如果是,则立即 return这种情况,但这只会增加不必要的复杂性。将方法重命名为更具描述性的名称(例如 import_file
、import_record
等,具体取决于您实际导入的内容)将是更好的解决方案。
import
有两个特殊之处:
除非 use
明确给出一个空导入列表(例如 use Foo ();
),否则 import
将在编译时作为 class 方法调用并传递任何导入已给出列表参数 use
。
如果 import
作为实例或 class 方法调用(无论是 use
隐式调用还是显式调用)并且不存在此类方法,将返回空列表而不是Can't locate object method
抛出错误或调用 AUTOLOAD。
如果今天实施,它可能会被称为 IMPORT
。
以上所有内容也适用于 unimport
(但使用 no
而不是 use
)。
更新:有些链接到文档,其中说 use
是 "exactly equivalent" 然后是谎言。
它完全等同于 BEGIN { require Module; Module::->VERSION(...); Module::->import(...) }
,只是如果没有指定版本则省略 VERSION 调用,如果给出明确的空列表则省略 import 调用(正如文档稍后阐明的那样)。
(另请注意 Module->import(如果存在则调用 Module() 函数,然后在任何 returns 上调用 import 方法)和 Module::->import 或'Module'->import 这是对模块 class 的直接 class 方法调用。)