Eche un vistazo al programa package MyCommonPkg.pm
y vea lo que dice. ¿Tiene algo como esto?
package MyCommonPkg;
use Exporter qw(import); # Might be "require" and not "use"
our @EXPORT = qw(thisSubroutineIsNotDefinedAnywhereElse);
La sintaxis puede ser un poco diferente. Las principales cosas que debería ver son la declaración package
, que está usando Exporter
y que la matriz @EXPORT
tiene el nombre de su subrutina.
Lo que está pasando es un conflicto de espacio de nombres. Su paquete está definiendo la misma subrutina que está definiendo.
Para evitar que esto suceda, Perl usa namespaces. De forma predeterminada, su espacio de nombre es main
. Sin embargo, se supone que los paquetes definen sus propios homónimos por separado usando el comando package
.
El espacio de nombre completo de una subrutina o variable es el espacio de nombre seguido de dos puntos dobles, seguido de la subrutina o el nombre de la variable. Por ejemplo, si mira File::Find, verá referencias a las variables $File::Find::name
y $File::Find::dir
. Estas son las variables $name
y $dir
dentro del paquete File/Find.pm
bajo el espacio de nombre File::Find
.
Con el fin de facilitar las cosas para usted, los paquetes pueden exportación sus variables y subrutinas en su principal espacio de nombres. Por ejemplo, si uso File::Copy, O puede hacer esto:
...
use File::Copy
...
copy ($file, $to_dir);
En lugar de:
...
use File::Copy
...
File::Copy::copy ($file, $to_dir);
Si nos fijamos en File/Copy.pm
, verá lo siguiente:
package File::Copy;
...
our(@ISA, @EXPORT, @EXPORT_OK, $VERSION, $Too_Big, $Syscopy_is_copy);
...
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(copy move);
El package File::Copy;
define un espacio de nombres. El require Exporter;
y el @ISA = qw(Exporter)
permiten que el paquete exporte subrutinas y variables en el espacio de nombre principal. El @EXPORT
automáticamente, sin que le diga nada, importa las subrutinas copy
y move
en el principal namespace si las quiere o no!
Ese último bit es muy importante. Ahora se considera malos modales para usar @EXPORT
. En su lugar, debe usar @EXPORT_OK
, que requiere que liste las subrutinas que desea usar. Los paquetes más modernos como Scalar::Util hacen esto.
Así que varias cosas. Primero, ¿su MyCommonPkg
tiene una declaración package MyCommonPkg;
? Si no, debería. Esto evita que las subrutinas y las variables de los paquetes afecten su programa de maneras desagradables. Luego, puede usar @EXPORT
o @EXPORT_OK
.
Si MyCommonPkg
tiene una declaración package
, ¿usa @EXPORT
? De ser así, tiene varias formas de evitar este problema:
- Ignore la advertencia. Es solo una advertencia. Como sabe que está redefiniendo la subrutina y desea usar su definición de la subrutina, ignórela.
Usted puede hacer esto para desactivar el aviso que se redefine la subrutina:
use MyCommonPkg;
no warnings qw(redefine);
sub thisSubroutineIsNotDefinedAnywhereElse {
...
}
use warnings qw(redefine);
- Uso
require MyCommonPkg;
en lugar de use MyCommonPkg;
.Esto evitará la importación de cualquier subrutina o variable en su espacio de nombres, incluidas las que desee utilizar. Digamos que MyCommonPkg
define cuatro subrutinas: thisSubroutineIsNotDefinedAnywhereElse
, foo
, bar
y barfoo
. Para usar cualquiera de estas subrutinas.
que tiene que hacer esto:
my $answer = MyCommonPkg::foo($input);
No
divertido.
Utilice otro nombre para su subrutina. Debería haberse documentado que esta subrutina se define en MyCommonPkg
, y si desea usar MyCommonPkg
, no debe usar nombres de subrutinas que se exportan.
Por último, si MyCommonPkg
es bastante nuevo, y no se utiliza en docenas de programas, utilice @EXPORT_OK
en lugar de @EXPORT
, y asegurarse de que todos los programas que utilizan MyCommonPkg
se modifican para exportar las subrutinas que quieren:
De esta manera:
use MyCommonPkg qw(foo bar);
En este caso, sólo subrutinas foo
y bar
se exportan. Las subrutinas thisSubroutineIsNotDefinedAnywhereElse
y barfoo
no se exportan a su entorno.
¿Realmente declara 'paquete Common.pm'? Eso parece un error. – mob
¿Tiene dos paquetes con el mismo nombre? Eso puede causar una colisión del espacio de nombres. Siempre nombre sus paquetes para el archivo en el que se encuentran (reemplazando '/' con '::', y eliminando '.pm'). Esto también puede ocurrir si tienes * no * namespace, lo que realmente significa que estás en 'main'. – Ether
no, no lo declare Common.pm. Acabo de renombrar cosas para obtener un ejemplo de pseudo código up y typoed. Voy a editar – user210757