Em Perl como você escolher dinamicamente o método a ser usado como um retorno de chamada?

StackOverflow https://stackoverflow.com/questions/1039601

Pergunta

Em Perl, é bastante trivial para especificar uma referência de retorno de chamada ou código se seu pacote é conhecido:

package Foo;

sub foo { print "in foo" }

# and then
package main;

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

baz( \&Foo::foo );

E esta impressão in foo.

Vamos dizer que você tem um objeto, sempre tão trivial, como este:

package Foo;

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

Você pode procurar o método usando a maneira acima (\ & Package: Método) e chamá-lo como

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

Mas, às vezes (bem, muitas vezes) você não sabe o tipo explícito. Vamos dizer que há Foo, Bar, Baz, e todos eles têm seu próprio método blat. Você gostaria de obter a referência para o método adequado, com base no objeto em vez do pacote. Como você iria sobre isso?

Foi útil?

Solução

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

Se $ ref é undef, o seu objeto não pode Blat. Se $ ref não é undef, é uma referência código válido para a função em questão, adequado para ligar. "$ Obj -> $ ref (@args)"

Outras dicas

método Let Lookup fazer o trabalho para você:

$ 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

Se você precisa de uma referência, tenha em mente que o Perl não tem delegados, mas você pode chegar perto:

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";
}

Ainda mais perto seria:

my $delegate = sub { $obj->$ref };
#           or sub { $obj->$method }
print $delegate->(), "\n";
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top