2015-08-31 2 views
0

J'essaie de trouver une solution générale pour obtenir une référence à une méthode dans un module. Supposons que nous avons un module Hello.pm avec une seule méthode appelée "bonjour".Référence à une méthode dans un package

Dans un programme appelant, on pourrait écrire

use Hello; 
Hello->hello('Hi There'); 

Le module est défini comme:

package Hello; 
sub hello { 
my $object=shift; 
my $greeting=shift; 
say "$greeting"; 
return; 
} 
1; 

Comment puis-je obtenir une référence de code à mon test du module de bonjour? Finalement, je veux construire une table d'expédition et être capable de le charger avec n'importe quel nombre de méthodes situées dans d'autres modules.

Cela ne fonctionne pas:

my $code_ref=&{Hello->hello} 

et invoquer comme ceci:

$code_ref->('Hi There'); 

Toutes les idées? Merci!

Répondre

2

Vous souhaitez effectuer un appel de sous-programme ($code_ref->(...)), mais vous souhaitez appeler une méthode. Cela signifie que vous devrez créer un sous-programme qui appelle la méthode et obtenir une référence à ce sous-programme à la place. Comme le montre ci-dessous, cela est assez facile à faire:

my $code_ref = sub { Hello->hello(@_) }; 
+0

Malheureusement, cela ne fonctionne pas. Lorsque le sous-marin se trouve dans le même module ou le même programme d'appel, c'est simple: $ code_ref = & hello et pour exécuter je lancerais $ code_ref -> {$ argument) –

+3

Je vous assure que c'est le cas. 'my $ code_ref = sub {Bonjour-> Bonjour (@_)}; $ code_ref -> ('Hi There'); 'fera la même chose que' Hello-> bonjour ('Hi There'); '. – ikegami

+0

OK. Le problème que j'ai est que lors de l'obtention d'un code_ref, l'appel doit inclure le nom de l'objet. Donc $ code_ref = & Hello :: hello et ensuite l'appel est $ code_ref -> ('Bonjour', $ argument). Sans code_ref, le nom de l'objet est implicitement passé. Malheureusement, je n'ai pas réussi à faire fonctionner votre format. Je dois faire quelque chose de mal. –

1

Si vous utilisez cela pour une table d'expédition, laissez la table faire le levage de charges lourdes en passant dans une clé au lieu de créer un CREF générique et dire quelle classe appeler le sous:

use warnings; 
use strict; 

package Hello; 
sub hello { 
    my $class = shift; 
    my $msg = shift; 
    print "$msg\n"; 
} 

package Bye; 
sub bye { 
    my $class = shift; 
    my $msg = shift; 
    print "$msg\n"; 
} 

package main; 

my %dt = (
    Hello => sub { Hello->hello(@_); }, 
    Bye => sub { Bye->bye(@_); }, 
); 

$dt{Hello}->("hi there"); 
$dt{Bye}->("see ya!"); 
+1

Ma réponse suppose que l'OP avait besoin d'un rappel car ils disaient qu'ils avaient besoin de l'appeler '$ code_ref -> ('Hi There')'. Si ce n'est pas un rappel, alors vous pouvez juste utiliser '$ class_or_obj -> $ nom_méthode (@args)' à la place d'une table de répartition. – ikegami

+0

Oui. C'était mon intention. J'ai appris les tables d'expédition de l'Ordre Supérieur Perl mais dans ses exemples tous ses sous-marins ont été définis dans le même fichier. Merci! –