创建全局变量
当你第一次在代码中写下$x的时候你就创建了一个全局变量。它在你使用的文件的任何地方可见。如果它是定义在一个包中,那么它就在这个包的内部是可见的,但是在mod_perl下运行你的代码,你必须要使用strict参数才能实现上面所述。
打开strict参数,创建全局变量
首先使用:
use strict;
然后使用:
use vars qw($scalar %hash @array);
这时这些变量在其被定义的包中成为全局变量,如果你想在包与包之间共享全局变量的话,我们要在下面来实现。
使用Exporter.pm来共享全局变量
假设你想在模块之间共享CGI.pm的一个对象(在这里我用$q表示)。我们在script.pl创建这个对象,但是却像是它在My:HTML中可见,首先把$q设为全局变量。
script.pl:
----------------
use vars qw($q);
use CGI;
use lib qw(.);
use My::HTML qw($q); # My/HTML.pm in the same dir as script.pl
$q = new CGI;
My::HTML::printmyheader();
----------------
注意,我们从My::HTML引入$q,并且My::HTML做了$q的输出工作。
My/HTML.pm
----------------
package My::HTML;
use strict;
BEGIN {
use Exporter ();
@My::HTML::ISA = qw(Exporter);
@My::HTML::EXPORT = qw();
@My::HTML::EXPORT_OK = qw($q);
}
use vars qw($q);
sub printmyheader{
# Whatever you want to do with $q... e.g.
print $q->header();
}
1;
-------------------
这样$q被在My::HTML包和script.pl程序间共享。反之亦然,如果你在My::HTML中创建对象而在script.pl中使用,也可共享。你所实现的是真正意义的共享,因为如果你在script.pl中改变了$q变量的话,在My::HTML中它也被同时改变了。
要是想在多于两个包中共享$q,应该怎么办呢?下面的例子是你还想在My::Doc中共享$q对象:
不必改变My::HTML包,修改script.pl加入:
use My::Doc qw($q);
然后,按照My::HTML的格式创建My::Doc模块——当然它们的内容是不同的。
如果你想在My::HTML中和script.pl中都使用My::Doc的话,必须还要在My::HTML中加入:
use My::Doc qw($q);
$q才会被共享。否则My::Doc不再共享$q。下面的代码给予了更清晰的说明:
script.pl:
----------------
use vars qw($q);
use CGI;
use lib qw(.);
use My::HTML qw($q); # My/HTML.pm in the same dir as script.pl
use My::Doc qw($q); # Ditto
$q = new CGI;
My::HTML::printmyheader();
----------------
My/HTML.pm
----------------
package My::HTML;
use strict;
BEGIN {
use Exporter ();
@My::HTML::ISA = qw(Exporter);
@My::HTML::EXPORT = qw();
@My::HTML::EXPORT_OK = qw($q);
}
use vars qw($q);
use My::Doc qw($q);
sub printmyheader{
# Whatever you want to do with $q... e.g.
print $q->header();
My::Doc::printtitle('Guide');
}
1;
-------------------
My/Doc.pm
----------------
package My::Doc;
use strict;
BEGIN {
use Exporter ();
@My::Doc::ISA = qw(Exporter);
@My::Doc::EXPORT = qw();
@My::Doc::EXPORT_OK = qw($q);
}
use vars qw($q);
sub printtitle{
my $title = shift || 'None';
print $q->h1($title);
}
1;
-------------------
使用变量别名来共享全局变量
像题目所说的,你可以不使用Exporter.pm就能把变量引入脚本或模块中。我发现把所有的配置变量保存在一个模块My::Config中非常有用,但是在其它模块中使用的时候我又不得不把它们全部输出。这样有两点不好之处:多余的标记会“污染”其它模块的命名空间,还会导致内存需求的增加。系统开销会加大,因为要保存对从配置模块输出变量及向其它模块的输入变量。我解决这个问题的方法是把这些所有的变量保存到一个哈系数组%c中。这有一个My::Config模块的例子:
package My::Config;
use strict;
use vars qw(%c);
%c = (
# All the configs go here
scalar_var => 5,
array_var => [
foo,
bar,
],
hash_var => {
foo => 'Foo',
bar => 'BARRR',
},
);
1;
现在在包中要使用配置变量,我只要用它的全名就可以了,如$My::Config::test。那么现在既然只有一个变量需要处理,事情就变得简单多了,也可以省去载入Exporter.pm包的开销。我们可以使用Perl的别名特性(aliasing)来进行变量的输出,也可以省去总要敲一大串键盘。
package My::HTML;
use strict;
use lib qw(.);
# Global Configuration now aliased to global %c
use My::Config (); # My/Config.pm in the same dir as script.pl
use vars qw(%c);
*c = \%My::Config::c;
# Now you can access the variables from the My::Config
print $c{scalar_val};
print $c{array_val}[0];
print $c{hash_val}{foo};
当然,你以上述方法描述的$c是在各处可见的全局变量,如果你在某处改变它的值,则会影响到你在其它模块中定义的My::Config::c的变量别名。
注意,别名仅在全局或是以local()定义的变量中有效,你不能这样写:
my *c=\%My::Config::c;
那是错误的,但是你可以这样写:
local *c=\%My::Config::c;
|