我试图从类中调用原型函数而不实例化对象。我的班级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;
我想从脚本main.pl
调用原型:
use strict;
use warnings;
use MyClass;
myprot {
print "myprot\n";
};
我收到了错误:
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.
我真的不明白未定义的子例程错误:使用use
,调用import
来定义main.pl
的原型。我也真的不明白未初始化的值错误。
我会很高兴得到一些解释。
答案 0 :(得分:8)
您正在寻找出口商。
package MyClass;
use strict;
use warnings;
use Exporter qw( import );
our @EXPORT = qw( myprot );
sub myprot(&) {
my ($f) = @_;
$f->();
}
1;
我通常使用@EXPORT_OK
(需要使用use MyClass qw( myprot );
),而不是默认导出。
答案 1 :(得分:5)
该代码中有一堆粗略的事情。
未经检查使用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...
你必须首先关闭严格。这通常称为“别名”。
no strict 'refs';
*{$caller.'::myprot'} = \&myprot;
预先设置原型是不必要的,别名将为您处理。
事实证明这是不必要的,有很多模块可以帮到你。最常见的是Exporter并附带Perl。这会使您的自定义import
变得不必要。
use Exporter 'import';
our @EXPORT = qw(myprot);
其他一般提示......
应该避免对类中的类的名称进行硬编码(即。\&MyClass::myprot
应该只是\&myprot
)。这使得更改类或移动代码变得更加困难。
不鼓励使用类和导出功能的混合模块。它们更难以使用,测试和记录并产生奇怪的副作用。您应该将myprot
放入其自己的模块中。
答案 2 :(得分:1)
你确定你真的想这样做吗?
问题是双引号会占用你在glob分配中的反斜杠。
eval "*${caller}::myprot = \&MyClass::myprot;"
应该是
eval "*${caller}::myprot = \\&MyClass::myprot;"
但请不要让我调试你的代码!