In Perl wie finden Sie dynamisch, welche Methode als Callback zu verwenden?
Frage
In Perl, es ist ziemlich trivial einen Rückruf oder Referenz-Code angeben, wenn sein Paket bekannt ist:
package Foo;
sub foo { print "in foo" }
# and then
package main;
sub baz {
my $code = shift;
$code->();
}
baz( \&Foo::foo );
Und das druckt in foo
.
Lassen Sie uns sagen Sie ein Objekt haben, noch so trivial, wie folgt aus:
package Foo;
sub new { bless {}, shift }
sub bar { print "in bar" }
sub baz { print "in baz" }
Sie können die Methode unter Verwendung der obigen Art und Weise nachschlagen (\ & Package: Methode) und nennen Sie es wie
package main;
my $foo = Foo->new();
my $ref = \&Foo::bar;
$foo->$ref();
Aber manchmal (okay, oft) Sie wissen nicht, den expliziten Typ. Nehmen wir an, es gibt Foo
, Bar
, Baz
, und sie alle haben ihre eigenen blat
Methode haben. Sie würden wollen den Verweis auf die entsprechende Methode erhalten, bezogen auf das Objekt anstelle des Pakets. Wie würden Sie das gehen über?
Lösung
my $ref = $obj->can('blat');
Wenn $ ref undef ist, das Objekt kann nicht Blat. Wenn $ ref nicht undef, es ist ein gültiger Code Bezug auf die betreffende Funktion, geeignet für Ihren Anruf. "$ Obj -> $ ref (@args)"
Andere Tipps
Lassen Methode Lookup tun, um die Arbeit für Sie:
$ 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
Wenn Sie eine Referenz benötigen, bedenken Sie, dass Perl nicht delegiert hat, aber Sie können in der Nähe bekommen:
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";
}
Noch näher wäre:
my $delegate = sub { $obj->$ref };
# or sub { $obj->$method }
print $delegate->(), "\n";