2

在 Perl 中,如果它的包是已知的,那么指定一个回调或代码引用是非常简单的:

package Foo;

sub foo { print "in foo" }

# and then
package main;

sub baz {
    my $code = shift;
    $code->();
}

baz( \&Foo::foo );

这打印出来in foo

假设您有一个非常简单的对象,如下所示:

package Foo;

sub new { bless {}, shift }
sub bar { print "in bar" }
sub baz { print "in baz" }

您可以使用上述方式(\&Package:Method)查找方法并将其称为

package main;
my $foo = Foo->new();
my $ref = \&Foo::bar;
$foo->$ref();

但有时(好吧,经常)你不知道显式类型。假设有Foo, Bar, Baz,它们都有自己的blat方法。您希望基于对象而不是包来获取对适当方法的引用。你会怎么做呢?

4

2 回答 2

8
my $ref = $obj->can('blat');

If $ref is undef, your object can't blat. If $ref is not undef, it's a valid CODE reference to the function in question, suitable for calling "$obj->$ref(@args)".

于 2009-06-24T17:00:49.943 回答
4

让方法查找为您完成工作:

$ cat try
#! /usr/bin/perl

use warnings;
use strict;

package Foo;
sub new { bless {} => shift }
sub blat { "Foo blat" }

package Bar;
sub new { bless {} => shift }
sub blat { "Bar blat" }

package Baz;
sub new { bless {} => shift }
sub blat { "Baz blat" }

package main;

my $method = "blat";
foreach my $obj (Foo->new, Bar->new, Baz->new) {
  print $obj->$method, "\n";
}

$ ./try
Foo blat
Bar blat
Baz blat

如果您需要参考,请记住 Perl 没有委托,但您可以接近:

my @objs = (Foo->new, Bar->new, Baz->new);

my $method = "blat";
my $obj = $objs[rand @objs];
my $ref = $obj->can($method);

if ($ref) {
  print $ref->($obj), "\n";
}
else {
  print "$obj: no can $method\n";
}

更接近的是:

my $delegate = sub { $obj->$ref };
#           or sub { $obj->$method }
print $delegate->(), "\n";
于 2009-06-24T16:59:26.827 回答