2010-03-04 9 views
1

Disons que si j'ai un module Perl Resounces.pm avec cet extrait de codePerl référence une méthode de classe

my $my_class = new MY_CLASS; 
our resource => { '/list' => $my_class->list_files() }; 

Alors puis-je appeler cette variable de ressource dans un autre script perl quelque chose de similaire comme ça?

use Resources; 
$Resources::resource->{'/list'}; 

Mon intention est d'exécuter la méthode list_files() lorsque j'utilise cette dernière déclaration. Est-ce que c'est possible?

+0

Quelle version de Perl? 5,8, 5,10, 6? – outis

+0

5.8, nous n'utilisons plus 5.6 - heureusement! – John

Répondre

4

Une option est d'utiliser un sous-programme anonyme:

package Resources; 
my $my_class = new MY_CLASS; 
our $resource = { '/list' => sub { $my_class->list_files(@_); } }; 

... 

package main; 
# dereference the code ref 
&{$Resources::resource->{'/list'}}; 
# or call it: 
$Resources::resource->{'/list'}(); 

Si vous changez ce $my_class références, seront également modifiés dans la fonction anonyme. Cela peut être ce que vous voulez; sinon, continuez à lire pour une fonction (bindMethod) qui lie un objet et une méthode.

Si vous ne voulez pas la fonction anonyme apparaisse sur la pile:

our $resource = { '/list' => sub { unshift @_, $my_class; 
            goto &MyClass::list_files; } }; 

Notez que cette forme de goto n'est pas l'habituel goto-déclaration, il est un tail call.

Vous pouvez définir une méthode d'assistance pour configurer la liaison, même si, honnêtement, cela ne vous rapportera pas grand-chose.

sub bindMethod { 
    my ($obj, $meth) = @_; 
    return sub { unshift @_, $obj; goto &{$meth}; } 
} 

my $my_class = new MyClass; 
our $resource = { '/list' => bindMethod($my_class, \&MyClass::list_files) }; 

est ici une version de bindMethod qui ne nécessite pas la classe à préciser le nom de la méthode.

sub bindMethod { 
    my ($obj, $meth) = @_; 
    if (! ref $meth) { 
     my $class = ref $obj; 
     $meth = \&{"${class}::$meth"}; 
    } 
    return sub { unshift @_, $obj; goto &{$meth}; } 
} 
... 
my $my_class = new MyClass; 
our $resource = { '/list' => bindMethod($my_class, 'list_files') }; 
+0

C'est exactement ce que je cherchais. Je vous remercie. – John

+1

@John: assurez-vous d'utiliser la version mise à jour. L'ancien n'a pas réussi à transmettre des arguments à la méthode enveloppée. – outis

+0

Merci encore. J'ai appris quelque chose de nouveau aujourd'hui - appel de queue. – John

Questions connexes