Toma un ejemplo más simple
package Foo { sub new { die 7 } };
package Bar { sub new { die 42 } };
sub Foo { "Bar" }
Foo->new();
En el ejemplo anterior, la constante se Foo
resuelve en "Bar", por lo que esto llama "Bar"->new
no "Foo"->new
. ¿Cómo se detiene la resolución de la subrutina? Puedes citarlo.
"Foo"->new();
En cuanto a la implicación del rendimiento, las cosas no empeoran al usar una cadena en lugar de una palabra desnuda. He confirmado que el optree generado por O=Deparse
es el mismo. Entonces, como regla general, parece que es mejor citar los nombres de clase si valoras la corrección.
Esto se menciona en Programming Perl (lamentablemente en el contexto de la invocación indirecta de métodos )
... así que le diremos que casi siempre puede salirse con un nombre de clase desnudo, siempre que dos cosas sean ciertas. Primero, no hay una subrutina con el mismo nombre que la clase. (Si sigue la convención de que los nombres de subrutinas como new
start minúsculas y los nombres de clase como ElvenRing
start mayúsculas , esto nunca será un problema). En segundo lugar, la clase se cargó con uno de
use ElvenRing;
require ElvenRing;
Cualquiera de estas declaraciones asegura que Perl sabe que ElvenRing
es un nombre de módulo, lo que obliga a que cualquier nombre simple como new
antes del nombre de la clase ElvenRing
se interprete como una llamada al método, incluso si usted declara una new
subrutina propia en el paquete actual.
Y eso tiene sentido: la confusión aquí solo puede ocurrir si sus subrutinas (generalmente en minúsculas) tienen el mismo nombre que una clase (generalmente en mayúsculas). Esto solo puede suceder si viola esa convención de nomenclatura anterior.
tldr; Probablemente sea una buena idea citar sus nombres de clase, si los conoce y valora la corrección sobre el desorden.
Nota al margen: alternativamente, puede detener la resolución de una palabra sin formato a una función fijando ::
a al final de la misma, por ejemplo en lo anterior Foo::->new
.
Gracias a Ginnz en reddit por señalarme esto , y a Toby Inkster por el comentario (aunque no tenía sentido para mí en la primera lectura).
Foo::->new
, como aprendí de ikegami.Foo::
tiene la ventaja de que avisa siFoo
no es un paquete existenteFoo->
se puede esperar que sepa que no hay tal subrutina en su paquete. Pero si está utilizando Try :: Tiny y otros módulos externos de cpan / other, ¿quién puede decir si uno de ellos está usando un paquete Try y, de ser así, si hay un sub Tiny en él?Citar explícitamente el nombre de la clase en lugar de usar una palabra desnuda (que se trata como una cadena) es una de las tres formas de evitar la ambigüedad sintáctica. La sección Métodos de clase de invocación de la documentación de perlobj explica.
Vea este extraño caso en acción con la demostración a continuación.
Su salida es
El resto de la sección de documentación mencionada anteriormente muestra cómo protegerse contra comportamientos sorprendentes o errores involuntarios.
Aplicando a su pregunta, todas las llamadas a continuación son equivalentes.
Añadir
::
al final tiene la ventaja de producir una advertencia útil. Digamos que accidentalmente escribisteEso produce
fuente