如何将模块的函数作为Perl中另一个模块的引用传递?

时间:2013-09-29 19:09:17

标签: perl oop reference function-pointers perl-module

如何在另一个模块的函数调用中将对模块函数的引用作为参数传递?
我尝试了以下(简单示例):
这是一个具有函数(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());但仍然无效 我在这做错了什么

5 个答案:

答案 0 :(得分:3)

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

$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') );

答案 1 :(得分:1)

我认为这可以用于:

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

传递方法参考。

你现在的位置

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

你需要

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

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

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

if( $employee->is_ok() ) { 

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

答案 2 :(得分:1)

在这个表达式中:

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

你说的是“调用方法$emp->is_ok,获取返回值,将其视为CODE引用,取消引用它,并返回对它的引用。这不起作用,因为该子类的返回值不是CODE引用。

要执行您想要的操作,您可以使用对匿名子的引用来包含对对象方法的调用:

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

答案 3 :(得分:1)

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

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

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

答案 4 :(得分: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);