2010-08-31 3 views
0

У меня есть модуль Perl (Module.pm), который инициализирует ряд переменных, некоторые из которых я хотел бы импортировать ($ VAR2, $ VAR3) в дополнительные подмодули, которые он мог бы загружать во время выполнение.Perl Импорт переменных из вызывающего модуля

Путь я в настоящее время настройки Module.pm выглядит следующим образом:

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'}; 
} 

Каждый подмодуль структурирована следующим образом:

package Module::SubModule1; 

use warnings; 
use strict; 
use Carp; 

use vars qw(); 

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

Я хочу, чтобы иметь возможность импортировать $ var2 и $ VAR3 в каждый из подмодулей без необходимости ссылаться на них как на $ Module :: VAR2 и $ Module :: VAR3. Я заметил, что вызывающий скрипт имеет доступ к обеим переменным, которые я экспортировал в Module.pm желаемым образом, но SubModule1.pm и SubModule2.pm все равно должны ссылаться на переменные как на Module.pm.

Я попытался обновить каждый подмодуль следующим образом, который, к сожалению, не получилось, я надеялся:

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; 
} 

Пожалуйста, дайте мне знать, как я могу успешно экспортировать $ var2 и $ var3 от Module.pm в каждом подмодуль. Заранее спасибо за вашу помощь!

ответ

5

В своих подмодулях, вы забыв сказать

use Module; 

? Вызов use Module из другого пакета (скажем Module::Submodule9) попытается запустить метод Module::import. Поскольку у вас нет этого метода, он вызовет метод Exporter::import, и именно там произойдет волшебство, которое экспортирует переменные Module в пространство имен Module::Submodule9.


В программе есть только один Module имен и только один экземпляр (глобальной) переменной $Module::VAR2. Экспорт создает псевдонимы для этой переменной в других пространствах имен, поэтому к одной и той же переменной можно обращаться по-разному. Попробуйте это в отдельном скрипте:

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

правило - я думал, что создаст ситуацию с несколькими экземплярами, так как мне нужен только один экземпляр Module.pm, который запускает и разделяет его GLOBAL-переменные в SubModule1.pm и SubModule2.pm, так что если функция в SubModule1.pm изменяет $ VAR2 то эта модификация будет доступна через Module.pm и другие подмодули. Добавил бы «Use Module»; как вы предложили в подмодулях создать этот желаемый эффект? Если нет, как еще это можно сделать? –

+2

Да, это будет иметь желаемый эффект, но если ваш желаемый эффект заключается в том, чтобы сфокусировать поведение глобальных переменных в одном пакете, которые произвольно изменены другим, вам следует серьезно пересмотреть ваш дизайн. – friedo

+0

@friedo - Мне хотелось бы посоветовать, как мы можем рассмотреть возможность изменения дизайна, поскольку я знаю, что он не идеален для использования или изменения GLOBALS. Причина, по которой я хочу, чтобы эти переменные были глобальными, заключается в том, что Module.pm действует нашим контроллером и настраивает группу глобальных переменных, таких как URL нашего домена, расположение каталога данных и т. Д. Так как Module.pm загружается любые подмодули, необходимые для отображения соответствующей страницы, я хотел бы, чтобы все подмодули могли ссылаться, использовать и в некоторых особых обстоятельствах изменять эти глобальные переменные. Есть ли еще один идеальный способ установить это? –

0

Ну есть простой способ:

В 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; 

В 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; 

В сценарии:

#!/usr/bin/perl 

use strict; 
use warnings; 

use M; 
use M::S; 

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

Но я бы посоветовал против этого. Глобальные переменные не являются хорошей практикой, и обмен глобальными переменными между модулями еще хуже.

+0

Причина, по которой у меня есть Module.pm и настройка подмодулей, как и я, заключается в том, что вызывающий скрипт не должен явно запрашивать использование необходимых подмодулей. Есть ли другой способ настроить это, что будет иметь тот же эффект, но потребует только, чтобы вызывающий скрипт использовал «Модуль»? –

+0

Чтобы ответить на ваш последний комментарий, причиной, по которой я хочу, чтобы эти переменные были глобальными, заключается в том, что Module.pm действует нашим контроллером и настраивает группу глобальных переменных, таких как URL-адрес нашего домена, расположение каталога данных и т. Д. Поскольку Module.pm затем загружает все подмодули, необходимые для отображения соответствующей страницы, я хотел бы, чтобы все подмодули могли ссылаться, использовать и в пару особых обстоятельств изменять эти глобальные переменные. –

+0

@ Russell C. Он по-прежнему будет работать. Там, где происходит 'use' /' require', это не имеет большого значения. Важно то, что '$ foo' является псевдонимом' $ M :: foo'. –

Смежные вопросы