2010-08-31 132 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