你的朋友是can http://perldoc.perl.org/UNIVERSAL.html。如果子例程存在,则返回对子例程的引用,否则返回 null。它甚至可以正确地沿着面向对象链向上走。
$self->{tests} = [
$self->can('_sub1'),
$self->can('_sub2'),
];
# later
for $tn (0..$#{$self->{tests}}) {
ok defined $self->{tests}[$tn], "Function $tn is available.";
}
# and later
my $ref = $self->{tests}[0];
$self->$ref(@args1);
$ref = $self->{tests}[1];
$self->$ref(@args2);
或者,感谢this https://stackoverflow.com/questions/2804109/how-do-i-use-an-index-in-an-array-reference-as-a-method-reference-in-perl问题(这恰好是this https://stackoverflow.com/questions/1836178/how-do-i-call-a-function-name-that-is-stored-in-a-hash-in-perl问题),你可以直接调用它:
$self->${\$self->{tests}[0]}(@args1);
$self->${\$self->{tests}[1]}(@args1);
请注意,\
给我们一个对 subref 的引用,然后它被取消引用${}
after $self->
. Whew!
为了解决 Brain d foy 提到的及时性问题,另一种方法是简单地使 {test} 本身成为一个子例程,它返回一个 ref,然后你就可以在你需要的时候得到它:
sub tests {
return [
$self->can('_sub1'),
$self->can('_sub2')
];
}
然后使用它:
for $tn (0..$#{$self->tests()}) {
...
}
当然,如果您无论如何都必须迭代引用,您也可以直接将引用传递出去:
for my $ref (0..$#{$self->tests()}) {
$self->$ref(@args);
}