Perl原型子程序在课堂上

时间:2014-12-01 19:41:09

标签: 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;

我想从脚本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的原型。我也真的不明白未初始化的值错误。 我会很高兴得到一些解释。

3 个答案:

答案 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;"

但请不要让我调试你的代码!