Prenons un exemple plus simple
package Foo { sub new { die 7 } };
package Bar { sub new { die 42 } };
sub Foo { "Bar" }
Foo->new();
Dans l'exemple ci-dessus, la constante se Foo
résout en "Bar", donc cela n'appelle "Bar"->new
pas "Foo"->new
. Comment empêchez-vous la résolution du sous-programme? Vous pouvez le citer.
"Foo"->new();
Quant à l'implication des performances, les choses ne sont pas aggravées en utilisant une chaîne plutôt qu'un mot simple. J'ai confirmé que l'optree généré par O=Deparse
est le même. Donc, en règle générale, il semble préférable de citer les noms de classe si vous appréciez l'exactitude.
Ceci est mentionné dans Programming Perl, (malheureusement dans le contexte de l' invocation de méthode indirecte )
... nous allons donc vous dire que vous pouvez presque toujours vous en sortir avec un nom de classe nu, à condition que deux choses soient vraies. Tout d'abord, il n'y a pas de sous-programme du même nom que la classe. (Si vous suivez la convention selon laquelle les noms de sousnew
ElvenRing
- programmes comme start minuscule et les noms de classe comme start majuscule , ce n'est jamais un problème). Deuxièmement, la classe a été chargée avec l'un des
use ElvenRing;
require ElvenRing;
L'une ou l'autre de ces déclarations garantit que Perl sait qu'il ElvenRing
s'agit d'un nom de module, ce qui force tout nom nu comme new
avant le nom de classe ElvenRing
à être interprété comme un appel de méthode, même si vous avez déclaré un new
sous - programme de votre choix dans le package actuel.
Et cela a du sens: la confusion ici ne peut se produire que si vos sous-programmes (généralement en minuscules) ont le même nom qu'une classe (généralement en majuscules). Cela ne peut se produire que si vous violez la convention de dénomination ci-dessus.
tldr; c'est probablement une bonne idée de citer vos noms de classe, si vous les connaissez et que vous appréciez l'exactitude par rapport à l'encombrement.
Remarque: vous pouvez également arrêter la résolution d'un mot nu à une fonction en apposant un ::
à la fin de celle-ci, par exemple dans ce qui précède Foo::->new
.
Merci à Ginnz sur reddit de me l'avoir signalé , et à Toby Inkster pour le commentaire (même si cela n'avait pas de sens pour moi à la première lecture).
Foo::->new
, comme je l'ai appris d'ikegami.Foo::
a l'avantage qu'il avertit si ceFoo
n'est pas un paquet existantFoo->
vous pouvez vous attendre à savoir qu'il n'y a pas un tel sous-programme dans votre package. Mais si vous utilisez Try :: Tiny et un certain nombre d'autres modules cpan / autres sources externes, qui peut dire si l'un d'eux utilise un package Try, et si oui, s'il contient un sous-marin Tiny?La citation explicite du nom de classe plutôt que l'utilisation d'un mot nu (qui est traité comme une chaîne) est l'une des trois façons d'éviter l'ambiguïté syntaxique. La section Invoking Class Methods de la documentation de perlobj explique.
Voir ce cas étrange en action avec la démo ci-dessous.
Sa sortie est
Le reste de la section de documentation susmentionnée montre comment se protéger contre un comportement surprenant ou des erreurs involontaires.
S'appliquant à votre question, tous les appels ci-dessous sont équivalents.
L'ajout
::
à la fin a l'avantage de produire un avertissement utile. Dites que vous avez accidentellement tapéCela produit
la source