2010-08-31 88 views
0

我有一个Perl模块(Module.pm),用于初始化一些变量,其中一些我想将它导入($ VAR2,$ VAR3)到其可能载入的其他子模块中执行。Perl从调用模块导入变量

我目前正在设立Module.pm的方法如下:

package Module::SubModule1; 

use warnings; 
use strict; 
use Carp; 

use vars qw(); 

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

我希望能够导入$ VAR2:

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

每个子模块的结构如下和$ 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; 
} 

请让我知道我能成功地从Module.pm出口$ VAR2和$ VAR3到每个子模块。在此先感谢您的帮助!

回答

5

在你的子模块,你忘了说

use Module; 

?从另一个包(称为Module::Submodule9)调用use Module将尝试运行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的一个实例运行并在SubModule1.pm和SubModule2.pm中共享它的GLOBAL变量,所以基本上如果SubModule1.pm中的函数修改$ VAR2那么可以通过Module.pm和其他子模块访问该修改。将添加'使用模块;'正如您在子模块中所建议的那样创建了这种期望的效果?如果不是的话,还有什么可以完成的呢? – 2010-08-31 20:50:14

+2

是的,它会产生所需的效果,但如果您希望的效果是将行为从一个包中任意更改的包中移除,那么您会很好地重新考虑您的设计。 – friedo 2010-08-31 21:12:31

+0

@friedo - 我很乐意提供一些关于改变设计方式的建议,因为我知道使用或更改GLOBALS并不理想。我希望这些变量是全局的原因是因为Module.pm正在作为我们的控制器并设置了一堆GLOBAL变量,如我们的域的URL,数据目录的位置等。由于Module.pm然后正在加载无论需要哪个子模块来呈现相应的页面,我都希望所有子模块能够引用,使用,并且在一些特殊情况下修改这些全局变量。还有另一种更理想的方法来设置它吗? – 2010-08-31 21:21:46

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和子模块设置的原因是,调用脚本不必明确地要求使用它所需的子模块。有没有另外一种方法来设置这个效果相同,但只需要调用脚本'使用模块'? – 2010-08-31 20:51:52

+0

为了解决您的最后一条评论,我希望这些变量是全局的原因是因为Module.pm正在充当我们的控制器并设置了一堆GLOBAL变量,如我们的域的URL,数据目录的位置等。 Module.pm然后加载它需要的任何子模块来渲染适当的页面,我希望所有的子模块能够引用,使用,并在几个特殊情况下修改这些全局变量。 – 2010-08-31 20:58:58

+0

@Russell C.它仍然有效。 'use'/'require'的出现并不重要。重要的是'$ foo'是'$ M :: foo'的别名。 – 2010-08-31 21:35:07