[英]How do I use an index in an array reference as a method reference in Perl?
类似于关于迭代子例程引用的问题 ,并且作为回答关于OO调度表的这个问题的结果,我想知道如何在引用中调用方法引用,而不是先删除它,或者甚至是否可能。
例如:
package Class::Foo;
use 5.012; #Yay autostrict!
use warnings;
# a basic constructor for illustration purposes....
sub new {
my $class = shift;
return bless {@_}, $class;
}
# some subroutines for flavor...
sub sub1 { say 'in sub 1'; return shift->{a} }
sub sub2 { say 'in sub 2'; return shift->{b} }
sub sub3 { say 'in sub 3'; return shift->{c} }
# and a way to dynamically load the tests we're running...
sub sublist {
my $self = shift;
return [
$self->can('sub1'),
$self->can('sub3'),
$self->can('sub2'),
];
}
package main;
sub get_index { ... } # details of how we get the index not important
my $instance = Class::Foo->new(a => 1, b => 2, c => 3);
my $subs = $instance->sublist();
my $index = get_index();
# <-- HERE
那么,在HERE,我们可以做到:
my $ref = $subs->[$index];
$instance->$ref();
但是如果不首先删除引用,我们将如何做到这一点呢?
编辑:
更改了代码示例,以便人们不会对实现细节感到困惑(叹息,尽我所能)。 这与我给出的第一个链接之间的重要区别在于, 函数应该作为方法调用 ,而不是作为直接子例程调用。
编辑2:
如上所述,你可以逃脱
$tests->[$index]();
因为你问题中的方法不是使用$self
。
你可以明确地传递$instance
,但这很笨重。 更好的是模拟具有闭包的代理:
sub sublist {
my $self = shift;
my $sublist;
for (qw/ sub1 sub3 sub2 /) {
my $meth = $_;
push @$sublist => sub { $self->$meth() };
}
return $sublist;
}
如果您想简洁,请使用
sub sublist {
my $self = shift;
return [ map { my $meth = $_; sub { $self->$meth() } }
qw/ sub1 sub3 sub2 / ];
}
随机拨打一个仍然是
$tests->[$index]();
但现在方法得到了调用。
通过can
抓取subrefs似乎是不必要的复杂性。 如果运行时确定要调用的方法名称列表,则可以大大简化代码:
sub sublist {
my $self = shift;
return [ qw/ sub1 sub3 sub2 / ];
}
下面,我们将它们全部称为测试目的,但您也可以看到如何只调用一个:
foreach my $method (@$subs) {
my $x = $instance->$method();
say "$method returned $x";
}
输出:
in sub 1 sub1 returned 1 in sub 3 sub3 returned 3 in sub 2 sub2 returned 2
(临时占位符在此处,除非答案的原始海报返回):
诀窍是添加一个解除引用:
$instance->${\$sublist->[$index]}(@args);
因此你也可以这样做:
$instance->${\$instance->sublist->[$index]}(@args);
否则它认为这是一个取消引用的标量。 (例如, Not a SCALAR reference at script.pl, line XX
)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.