简体   繁体   English

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

[英]How can I pass a module's function as a reference to another module in Perl?

How can I pass a reference to a module's function as parameter in a function call of another module? 如何在另一个模块的函数调用中将模块函数的引用作为参数传递?
I tried the following (simple example): 我尝试了以下(简单示例):
This is the module that has a function (process_staff) that takes as a parameter a function reference (is_ok). 这是具有函数(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; 

This is the module that implements the passed function (is_ok) 这是实现传递函数的模块(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;  
}   

This is my test script that I run: 这是我运行的测试脚本:

#!/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  

I get a: 我得到一个:

Not a CODE reference at testScript.pl line 14.  

I also tried: $processor->process_staff(\\&$emp->is_ok()); 我也尝试过: $processor->process_staff(\\&$emp->is_ok()); but also still does not work. 但仍然无法正常工作。
What am I doing wrong here 我在这做错了什么

You appear to want to pass an object and a method to call on it; 您似乎想要传递一个对象和一个方法来调用它; the easiest way to do that would be: 最简单的方法是:

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

where process_staff looks like: process_staff的位置如下:

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

or you can pass the reference and the object separately: 或者您可以单独传递引用和对象:

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

$processor->process_staff( $emp, $emp->can('is_ok') );

I think this could work with: 我认为这可以用于:

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

where you pass in the method ref. 你传入方法ref的地方。

and where you currently have 你现在的位置

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

you need 你需要

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

This is because you cannot reference named methods simply from an object, by the syntax \\&$obj->method . 这是因为您无法通过语法\\&$obj->method仅从对象引用命名\\&$obj->method

However, in your example code it is not at all clear why you don't do this instead: 但是,在您的示例代码中,您完全不清楚为什么不这样做:

if( $employee->is_ok() ) { 

in which case you would not need to reference the method to call in process_staff at all. 在这种情况下,您根本不需要引用在process_staff中调用的方法。 There are also other ways to achieve the same method indirection that might give you better encapsulation in future. 还有其他方法可以实现相同的方法间接,可能会在将来为您提供更好的封装。

In this expression: 在这个表达式中:

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

You are saying "call the method $emp->is_ok , take the return value, treat it as a CODE reference, dereference it, and return a reference to that. That doesn't work, since the return value from that sub is not a CODE reference. 你说的是“调用方法$emp->is_ok ,获取返回值,将其视为CODE引用,取消引用它,并返回对它的引用。这不起作用,因为该子句的返回值不是CODE参考。

To do what you want, you can use a reference to an anonymous sub to wrap the call to your object method: 要执行您想要的操作,您可以使用对匿名子的引用来包含对对象方法的调用:

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

You can pass anonymous coderef which returns result from desired method, 您可以传递匿名coderef,它返回所需方法的结果,

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

@_ can be dropped as is_ok method doesn't take any arguments. 可以删除@_因为is_ok方法不接受任何参数。

It's not specifically what you asked for, but I think you simply need the following: 这不是你要求的具体内容,但我认为你只需要以下内容:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM