2010-03-04 39 views
1

讓我們說,如果我有這個代碼片斷的Perl引用類方法

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

因此,我可以把這個資源變量在類似這樣的另一perl腳本一些Perl模塊Resounces.pm?

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

我的意圖是在使用最後一條語句時執行list_files()方法。這甚至有可能嗎?

+0

哪個Perl版本? 5.8,5.10,6? – outis

+0

5.8,我們不再使用5.6 - 謝天謝地! – John

回答

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') }; 
+0

這正是我所期待的。謝謝。 – John

+1

@John:確保你使用更新後的版本。舊的未能將參數傳遞給包裝的方法。 – outis

+0

再次感謝您。我今天學到了一些新東西 - 尾巴呼叫。 – John