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