use*_*275 2 perl class subroutine subroutine-prototypes
我试图从类中调用原型函数而不实例化对象.我班的一个例子MyClass:
package MyClass;
use strict;
use warnings;
sub import{
my $class = shift;
my ($caller) = caller();
eval "sub ${caller}::myprot(\&);";
eval "*${caller}::myprot = \&MyClass::myprot;";
}
sub myprot (&) {
my ($f) = @_;
$f->();
}
1;
Run Code Online (Sandbox Code Playgroud)
我想从脚本中调用原型main.pl:
use strict;
use warnings;
use MyClass;
myprot {
print "myprot\n";
};
Run Code Online (Sandbox Code Playgroud)
我收到错误:
Use of uninitialized value in subroutine entry at MyClass.pm line 14.
Use of uninitialized value in subroutine entry at MyClass.pm line 14.
Undefined subroutine &main::myprot called at main.pm line 8.
Run Code Online (Sandbox Code Playgroud)
我真的不明白未定义的子程序错误:使用use,import调用它来定义原型main.pl.我也真的不明白未初始化的值错误.我很乐意得到一些解释.
你正在寻找出口商.
package MyClass;
use strict;
use warnings;
use Exporter qw( import );
our @EXPORT = qw( myprot );
sub myprot(&) {
my ($f) = @_;
$f->();
}
1;
Run Code Online (Sandbox Code Playgroud)
我通常使用@EXPORT_OK(需要使用use MyClass qw( myprot );)而不是默认导出.
那段代码中有一堆粗略的东西.
未经检查的使用eval意味着如果失败,你永远不会知道.eval应该用作eval "code" or die $@.你会发现它引发了一个错误,因为当你弄乱符号表时,严格不喜欢它(*name = \&code正是这样做).
使用eval导出子程序是过度的.eval STRING是一个潜在的安全漏洞,应该作为最后的手段使用(eval BLOCK很好).您可以在没有eval的情况下操作符号表,但严格不会喜欢使用符号引用.
my $caller = "foo";
*{"${caller}::myprot"} = \&MyClass::myprot;
# Can't use string ("foo::myprot") as a symbol ref while "strict refs" in use...
Run Code Online (Sandbox Code Playgroud)
你必须首先关闭严格.这通常称为"混叠".
no strict 'refs';
*{$caller.'::myprot'} = \&myprot;
Run Code Online (Sandbox Code Playgroud)
预先设置原型是不必要的,别名将为您处理.
事实证明这一切都是不必要的,有很多模块可以帮到你.最常见的是Exporter和Perl.这使您的自定义import不必要.
use Exporter 'import';
our @EXPORT = qw(myprot);
Run Code Online (Sandbox Code Playgroud)
其他一般提示......
应该避免硬编码类中的类的名称(即\&MyClass::myprot应该只是\&myprot).这使得更改类或移动代码变得更加困难.
不鼓励使用类和导出功能的混合模块.它们更难以使用,测试和记录并产生奇怪的副作用.你应该把myprot它放进自己的模块中.