【问题标题】:Perl Importing Variables From Calling ModulePerl 从调用模块导入变量
【发布时间】:2011-04-06 11:49:25
【问题描述】:

我有一个 Perl 模块 (Module.pm),它初始化了许多变量,我想将其中一些变量 ($VAR2, $VAR3) 导入到可能在执行期间加载的其他子模块中。

我目前设置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 导出到每个子模块中。提前感谢您的帮助!

【问题讨论】:

    标签: perl oop perl-module


    【解决方案1】:

    在你的子模块中,你忘了说

    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
    

    【讨论】:

    • 规则 - 我认为这会产生多实例情况,因为我只希望 Module.pm 的 1 个实例运行并在 SubModule1.pm 和 SubModule2.pm 之间共享它的全局变量,所以基本上如果 SubModule1 中的函数.pm 修改 $VAR2 然后可以跨 Module.pm 和其他子模块访问该修改。将添加“使用模块;”正如您在子模块中所建议的那样,会产生这种预期的效果吗?如果没有,还有什么方法可以实现?
    • 是的,它会产生预期的效果,但如果您希望的效果是基于一个包中的全局变量的行为,而这些包被另一个包任意更改,那么您最好认真重新考虑您的设计。
    • @friedo - 我想就我们可以考虑更改设计的方式提供一些建议,因为我知道使用或更改 GLOBALS 并不理想。我希望这些变量是全局变量的原因是因为 Module.pm 充当我们的控制器并设置了一堆 GLOBAL 变量,例如我们域的 URL、数据目录的位置等。因为 Module.pm 然后正在加载无论它需要呈现适当的页面的任何子模块,我都希望所有子模块都能够引用、使用并在一些特殊情况下修改这些全局变量。还有其他更理想的设置方法吗?
    • @Russell:根本不要使用全局变量。使用 OO 设计,并将您的状态值存储在任何合适的类中。
    【解决方案2】:

    有一个简单的方法:

    在下午:

    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();
    

    但我建议不要这样做。全局变量不是一个好习惯,在模块之间共享全局变量更糟糕。

    【讨论】:

    • 我有 Module.pm 和子模块设置的原因是调用脚本不必明确要求使用它所需的子模块。是否有另一种设置方法可以产生相同的效果,但只需要调用脚本“使用模块;”?
    • 为了解决您的最后一条评论,我希望这些变量是全局变量的原因是因为 Module.pm 充当我们的控制器并设置了一堆 GLOBAL 变量,例如我们域的 URL、数据目录等。由于 Module.pm 正在加载渲染适当页面所需的任何子模块,我希望所有子模块都能够引用、使用并在一些特殊情况下修改这些全局变量。跨度>
    • @Russell C. 它仍然可以工作。 use/require 出现在哪里并不重要。重要的是$foo$M::foo 的别名。
    • 您也可以说our $foo; *foo = \$M::foo 在子模块中创建别名。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-28
    相关资源
    最近更新 更多