web-dev-qa-db-fra.com

Quelqu'un peut-il expliquer (mon $ self = shift) en Perl

J'ai vraiment du mal à comprendre l'intersection de OO Perl et my $self = shift; La documentation sur ces éléments individuels est excellente, mais aucun d'eux que j'ai trouvé ne touche à la façon dont ils fonctionnent ensemble.

J'ai utilisé Moose pour créer des modules avec des attributs, et bien sûr, il est utile de référencer l'attribut d'un module dans ledit module. On m'a dit maintes et maintes fois d'utiliser my $self = shift; dans un sous-programme pour affecter les attributs du module à cette variable. Cela a du sens et fonctionne, mais lorsque je passe également des arguments au sous-programme, ce processus prend clairement le premier élément du @ARGV array et l'assigne à $self ainsi que.

Quelqu'un peut-il expliquer comment je peux utiliser shift pour obtenir un accès interne aux attributs d'un module, tout en passant des arguments dans le @ARGV tableau?

28
Alex H Hadik

Tout d'abord, un sous-programme ne passe pas le tableau @ARGV. Tous les paramètres transmis à un sous-programme sont plutôt aplatis en une seule liste représentée par @_ À l'intérieur du sous-programme. Le tableau @ARGV est disponible au niveau supérieur de votre script, contenant les arguments de ligne de commande passés à votre script.

Maintenant, en Perl, lorsque vous appelez une méthode sur un objet, l'objet est implicitement passé en tant que paramètre à la méthode.

Si vous ignorez l'héritage,

 $obj->doCoolStuff($a, $b);

est équivalent à

 doCoolStuff($obj, $a, $b);

Ce qui signifie que le contenu de @_ Dans la méthode doCoolStuff serait: @_ = ($obj, $a, $b);

Maintenant, la fonction intégrée shift, sans aucun paramètre, décale un élément de la variable de tableau par défaut @_. Dans ce cas, ce serait $obj.

Donc quand vous faites $self = shift, Vous dites effectivement $self = $obj.

J'espère également que cela explique comment passer d'autres paramètres à une méthode via la notation ->. Poursuivant l'exemple que j'ai indiqué ci-dessus, ce serait comme:

sub doCoolStuff {
  # Remember @_ = ($obj, $a, $b)
  my $self = shift;
  my ($a, $b) = @_;

De plus, bien que Moose soit une excellente couche d'objet pour Perl, cela ne supprime pas l'exigence selon laquelle vous devez initialiser le $self Vous-même dans chaque méthode. Rappelez-vous toujours cela. Alors qu'un langage comme C++ et Java initialise implicitement la référence d'objet this, en Perl, vous devez le faire explicitement pour chaque méthode que vous écrivez.

59
Nikhil

Dans le code de niveau supérieur, shift() est l'abréviation de shift(@ARGV). @ARGV Contient les arguments de la ligne de commande.

Dans un sous, shift() est l'abréviation de shift(@_). @_ Contient les arguments du sous-marin.

Donc my $self = shift; Saisit le premier argument du sous-marin. Lors de l'appel d'une méthode, l'invocant (ce qui reste du ->) Est passé comme premier paramètre. En d'autres termes,

$o->method(@a)

est similaire à

my $sub = $o->can('method');
$sub->($o, @a);

Dans cet exemple, my $self = shift; Affectera $o À $self.

8
ikegami

Si vous appelez:

$myinstance->myMethod("my_parameter");  

est le même que faire:

myMethod($myinstance, "my_parameter");  

mais si vous le faites:

myMethod("my_parameter");  

seul "mon_paramètre" sera transmis.

ALORS si dans myMethod vous faites toujours:

 $self = shift @_;  

$ self sera la référence d'objet lorsque l'ID myMethod est appelé à partir d'un contexte d'objet
mais sera "mon_paramètre" lorsqu'il sera appelé à partir d'une autre méthode à l'intérieur d'une manière procédurale.
Soyez conscient de cela;

2
dg546gs4d65