4

如何在另一个模块的函数调用中传递对模块函数的引用作为参数?
我尝试了以下(简单示例):
这是具有函数(process_staff)的模块,该函数将函数引用(is_ok)作为参数。

#!/usr/bin/perl  
use strict;  
use warnings;  

package Objs::Processing;  

sub new {  
    my ($class) = @_;  
    bless {} ;      
}  

sub process_staff {  
    my ($employee, $func) = @_;  
    if($func->is_ok($employee)) {  
        print "Is ok to process\n";  
    }  
    else {  
        print "Not ok to process\n";  
    }  
}  
1; 

这是实现传递函数的模块(is_ok)

#!usr/bin/perl  
use strict;  
use warnings;  

package Objs::Employee;  

my $started;  

sub new {  
    my ($class) = @_;  
    my $cur_time = localtime;  
    my $self = {  
        started => $cur_time,  
    };  
    print "Time: $cur_time \n";  
    bless $self;  
}  

sub get_started {  
    my ($class) = @_;  
    return $class->{started};  
}  

sub set_started {  
    my ($class, $value) = @_;  
    $class->{started} = $value;  
}  

sub is_ok {  
    my ($emp) = @_;  
    print "In is ok I received:\n";  
    use Data::Dumper;   
    print Dumper($emp);  
    return 1;  
}   

这是我运行的测试脚本:

#!/usr/bin/perl  
use strict;  
use warnings;  

use Objs::Manager;  
use Objs::Processing;  

my $emp = Objs::Manager->new('John Smith');    
use Data::Dumper;    
print Dumper($emp);  

my $processor = Objs::Processing->new();   
$processor->process_staff(\&$emp->is_ok);   #error is here  

我得到一个:

Not a CODE reference at testScript.pl line 14.  

我也试过: $processor->process_staff(\&$emp->is_ok());但还是不行。
我在这里做错了什么

4

5 回答 5

4

您似乎想要传递一个对象和一个方法来调用它;最简单的方法是:

$processor->process_staff( sub { $emp->is_ok } );

其中 process_staff 看起来像:

sub process_staff {
    my ($self, $func) = @_;
    if ( $func->() ) {
        ...

或者您可以分别传递引用和对象:

sub process_staff {
    my ($self, $emp, $method) = @_;
    if ( $emp->$method() ) {
    ...

$processor->process_staff( $emp, $emp->can('is_ok') );
于 2013-09-29T19:53:29.447 回答
1

在这个表达式中:

$processor->process_staff(\&$emp->is_ok); 

您说的是“调用方法$emp->is_ok,获取返回值,将其视为CODE引用,取消引用它,然后返回对它的引用。这是行不通的,因为该子项的返回值不是CODE引用。

为了做你想做的事,你可以使用对匿名 sub 的引用来包装对你的对象方法的调用:

$processor->process_staff( sub { $emp->is_ok } );  
于 2013-09-29T19:53:21.093 回答
1

您可以传递匿名 coderef,它从所需方法返回结果,

$processor->process_staff(sub{ $emp->is_ok(@_) });

@_可以删除,因为is_ok方法不带任何参数。

于 2013-09-29T19:53:44.447 回答
1

这不是您要求的具体内容,但我认为您只需要以下内容:

sub process_staff {  
    my ($self, $emp) = @_;  
    if ($emp->is_ok()) {  
        print "Is ok to process\n";  
    }  
    else {  
        print "Not ok to process\n";  
    }  
}  

$processor->process_staff($emp);
于 2013-09-29T21:53:29.083 回答
1

我认为这可以与:

$processor->process_staff(\&Objs::Employee::is_ok);

传入方法 ref 的位置。

以及您目前拥有的地方

if( $func->is_ok($employee) ) { 

你需要

if( $func->( $employee ) ) { 

这是因为您不能通过语法简单地从对象引用命名方法\&$obj->method

但是,在您的示例代码中,根本不清楚您为什么不这样做:

if( $employee->is_ok() ) { 

在这种情况下,您根本不需要引用要调用的方法process_staff。还有其他方法可以实现相同的方法间接,将来可能会为您提供更好的封装。

于 2013-09-29T19:30:34.827 回答