In Perl, it's pretty trivial to specify a callback or code reference if its package is known:
package Foo;
sub foo { print "in foo" }
# and then
package main;
sub baz {
my $code = shift;
$code->();
}
baz( \&Foo::foo );
And this prints in foo
.
Lets say you have an object, ever so trivial, like this:
package Foo;
sub new { bless {}, shift }
sub bar { print "in bar" }
sub baz { print "in baz" }
You can look up the method using the above way (\\&Package:Method) and call it like
package main;
my $foo = Foo->new();
my $ref = \&Foo::bar;
$foo->$ref();
But sometimes (okay, often) you don't know the explicit type. Lets say there's Foo
, Bar
, Baz
, and they all have their own blat
method. You'd want to get the reference to the appropriate method, based on the object instead of the package. How would you go about that?
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)".
Let method lookup do the work for you:
$ 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
If you need a reference, keep in mind that Perl doesn't have delegates, but you can get close:
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";
}
Even closer would be:
my $delegate = sub { $obj->$ref };
# or sub { $obj->$method }
print $delegate->(), "\n";
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.