2010-08-31 6 views
0

J'ai un module Perl (Module.pm) qui initialise un certain nombre de variables, dont certaines que je voudrais importer ($ VAR2, $ VAR3) dans des sous-modules supplémentaires qu'il pourrait charger pendant exécution.Perl Importer des variables à partir du module d'appel

La façon dont je suis actuellement en place Module.pm la mise en est comme suit:

package Module; 

use warnings; 
use strict; 

use vars qw($SUBMODULES $VAR1 $VAR2 $VAR3); 

require Exporter; 
our @ISA = qw(Exporter); 
our @EXPORT = qw($VAR2 $VAR3); 

sub new { 
    my ($package) = @_; 
    my $self = {}; 
    bless ($self, $package); 
    return $self; 
} 

sub SubModules1 { 
    my $self = shift; 
    if($SUBMODULES->{'1'}) { return $SUBMODULES->{'1'}; } 

    # Load & cache submodule 
    require Module::SubModule1; 
    $SUBMODULES->{'1'} = Module::SubModule1->new(@_);  
    return $SUBMODULES->{'1'}; 
} 

sub SubModules2 { 
    my $self = shift; 
    if($SUBMODULES->{'2'}) { return $SUBMODULES->{'2'}; } 

    # Load & cache submodule 
    require Module::SubModule2; 
    $SUBMODULES->{'2'} = Module::SubModule2->new(@_);  
    return $SUBMODULES->{'2'}; 
} 

Chaque sous-module est structuré comme suit:

package Module::SubModule1; 

use warnings; 
use strict; 
use Carp; 

use vars qw(); 

sub new { 
    my ($package) = @_; 
    my $self = {}; 
    bless ($self, $package); 
    return $self; 
} 

Je veux être en mesure d'importer le $ Var2 et variables $ VAR3 dans chacun des sous-modules sans avoir à les référencer comme $ Module :: VAR2 et $ Module :: VAR3. J'ai remarqué que le script appelant est capable d'accéder aux deux variables que j'ai exportées dans Module.pm de la manière désirée mais SubModule1.pm et SubModule2.pm doivent toujours faire référence aux variables comme provenant de Module.pm.

J'ai essayé de mettre à jour chaque sous-module comme suit qui ne fonctionne malheureusement j'espérais:

package Module::SubModule1; 

use warnings; 
use strict; 
use Carp; 

use vars qw($VAR2 $VAR3); 

sub new { 
    my ($package) = @_; 
    my $self = {}; 
    bless ($self, $package); 
    $VAR2 = $Module::VAR2; 
    $VAR3 = $Module::VAR3; 
    return $self; 
} 

S'il vous plaît laissez-moi savoir comment je peux exporter avec succès $ et VAR2 $ VAR3 de Module.pm dans chaque sous-module. Merci d'avance pour votre aide!

Répondre

5

Dans vos sous-modules, êtes-vous Oublier de dire

use Module; 

? L'appel use Module à partir d'un autre package (par exemple Module::Submodule9) va essayer d'exécuter la méthode Module::import. Puisque vous n'avez pas cette méthode, elle appellera la méthode Exporter::import, et c'est là que la magie qui exporte les variables de Module dans l'espace de noms Module::Submodule9 va arriver.


Dans votre programme il n'y a qu'un espace de noms Module et une seule instance de la variable (globale) $Module::VAR2. L'exportation crée des alias pour cette variable dans d'autres espaces de noms, de sorte que la même variable peut être accédée de différentes manières. Essayez ceci dans un script séparé:

package Whatever; 
use Module; 
use strict; 
use vars qw($VAR2); 

$Module::VAR2 = 5; 
print $Whatever::VAR2; # should be 5. 
$VAR2 = 14;    # same as $Whatever::VAR2 = 14 
print $Module::VAR2;  # should be 14 
+0

règle - Je pensais que cela créerait une situation d'instance multiple puisque je veux seulement 1 instance de Module.pm en cours d'exécution et partage ses variables GLOBAL à travers SubModule1.pm et SubModule2.pm si fondamentalement si une fonction dans SubModule1.pm modifie $ VAR2 alors cette modification serait accessible à travers Module.pm et les autres sous-modules. Serait l'ajout de «utiliser le module; comme vous avez suggéré dans les sous-modules de créer cet effet désiré? Sinon, comment pourrait-il être accompli autrement? –

+2

Oui, cela aurait l'effet escompté, mais si l'effet que vous voulez obtenir est de baser le comportement des globales dans un paquet arbitrairement modifié par un autre, vous feriez bien de repenser sérieusement votre conception. – friedo

+0

@friedo - J'aimerais avoir des conseils sur les façons dont nous pourrions envisager de modifier le design puisque je sais que ce n'est pas idéal pour utiliser ou changer GLOBALS. La raison pour laquelle je veux que ces variables soient globales est parce que Module.pm agit en tant que notre contrôleur et met en place un tas de variables GLOBAL comme l'URL de notre domaine, l'emplacement du répertoire de données, etc. Puisque Module.pm est alors en train de charger quels que soient les sous-modules dont il a besoin pour rendre la page appropriée, je voudrais que tous les sous-modules puissent référencer, utiliser et, dans quelques circonstances particulières, modifier ces variables globales. Y a-t-il une autre façon plus idéale de mettre cela en place? –

0

Eh bien, il est un moyen facile:

En M.pm:

package M; 

use strict; 
use warnings; 

#our is better than "use vars" for creating package variables 
#it creates an alias to $M::foo named $foo in the current lexical scope 
our $foo = 5; 

sub inM { print "$foo\n" } 

1; 

En M/S.pm

package M; 

#creates an alias to $M::foo that will last for the entire scope, 
#in this case the entire file 
our $foo; 

package M::S; 

use strict; 
use warnings; 

sub inMS { print "$foo\n" } 

1; 

Dans le script:

#!/usr/bin/perl 

use strict; 
use warnings; 

use M; 
use M::S; 

M::inM(); 
M::S::inMS(); 

Mais je déconseille cela. Les variables globales ne sont pas une bonne pratique, et le partage des variables globales entre les modules est encore pire.

+0

La raison pour laquelle j'ai installé Module.pm et la configuration des sous-modules est que le script appelant n'a pas besoin de demander explicitement d'utiliser les sous-modules requis. Existe-t-il une autre façon de configurer ceci qui aurait le même effet mais nécessiterait seulement que le script appelant utilise 'Module'? –

+0

Pour répondre à votre dernier commentaire, la raison pour laquelle je veux que ces variables soient globales est que Module.pm agit en tant que notre contrôleur et établit un tas de variables GLOBAL comme l'URL de notre domaine, l'emplacement du répertoire de données, etc. Module.pm est alors en train de charger tous les sous-modules dont il a besoin pour afficher la page appropriée, je voudrais que tous les sous-modules puissent référencer, utiliser, et dans quelques circonstances particulières, modifier ces variables globales. –

+0

@Russell C. Cela fonctionnera toujours. Où le 'use' /' require' se produit n'a pas vraiment d'importance. Ce qui compte c'est que '$ foo' est un alias de' $ M :: foo'. –

Questions connexes