Perl引用了一个类方法

时间:2010-03-04 01:29:08

标签: perl

如果我有一个带有此代码段的Perl模块Resounces.pm

,请说明
my $my_class = new MY_CLASS;
our resource => { '/list' => $my_class->list_files() };

那么我可以在另一个类似的perl脚本中调用这个资源变量吗?

use Resources;
$Resources::resource->{'/list'};

我打算在使用最后一个语句时执行list_files()方法。这甚至可能吗?

1 个答案:

答案 0 :(得分:4)

一种选择是使用匿名子:

package Resources;
my $my_class = new MY_CLASS;
our $resource = { '/list' => sub { $my_class->list_files(@_); } };

...

package main;
# dereference the code ref
&{$Resources::resource->{'/list'}};
# or call it:
$Resources::resource->{'/list'}();

如果您更改$my_class引用,它也将在匿名函数中更改。这可能是你想要的;如果没有,请继续阅读绑定对象和方法的函数(bindMethod)。

如果您不希望匿名函数出现在堆栈中:

our $resource = { '/list' => sub { unshift @_, $my_class; 
                                   goto &MyClass::list_files; } };

请注意,这种形式的goto不是通常的goto语句 - 它是tail call

你可以定义一个帮助方法来设置绑定,但老实说它不会给你带来太大的帮助。

sub bindMethod {
    my ($obj, $meth) = @_;
    return sub { unshift @_, $obj; goto &{$meth}; }
}

my $my_class = new MyClass;
our $resource = { '/list' => bindMethod($my_class, \&MyClass::list_files) };

这是bindMethod的版本,不需要使用方法名称指定类。

sub bindMethod {
    my ($obj, $meth) = @_;
    if (! ref $meth) {
        my $class = ref $obj;
        $meth = \&{"${class}::$meth"};
    }
    return sub { unshift @_, $obj; goto &{$meth}; }
}
...
my $my_class = new MyClass;
our $resource = { '/list' => bindMethod($my_class, 'list_files') };