ChinaUnix首页 > 精华文章 > Perl > 正文

[精彩] perl中our的用法


http://www.chinaunix.net 作者:happig1  发表于:2005-06-06 15:51:53
发表评论】 【查看原文】 【Perl讨论区】【关闭

今天心血来潮看了一下ActivePerl下的Exporter.pm下的代码,发现里面有:
require 5.006;

# Be lean.
#use strict;
#no strict 'refs';

our $Debug = 0;
our $ExportLevel = 0;
our $Verbose ||= 0;
our $VERSION = '5.58';
our (%Cache);
我不知道这个our是什么意思,请知道的来指点迷津
还有就是那个require 5.006,这个有什么说法吗?
谢谢.



 大灰狼 回复于:2005-06-05 19:14:45

our EXPR
our EXPR TYPE
our EXPR : ATTRS
our TYPE EXPR : ATTRS
An {our} declares the listed variables to be valid globals within the enclosing block, file, or {eval}. That is, it has the same scoping rules as a ``my'' declaration, but does not create a local variable. If more than one value is listed, the list must be placed in parentheses. The {our} declaration has no semantic effect unless ``use strict vars'' is in effect, in which case it lets you use the declared global variable without qualifying it with a package name. (But only within the lexical scope of the {our} declaration. In this it differs from ``use vars'', which is package scoped.) 
An {our} declaration declares a global variable that will be visible across its entire lexical scope, even across package boundaries. The package in which the variable is entered is determined at the point of the declaration, not at the point of use. This means the following behavior holds:

    package Foo;
    our $bar;           # declares $Foo::bar for rest of lexical scope
    $bar = 20;


 flw 回复于:2005-06-05 19:37:37

require 5.006
当版本号小于 5.006 的时候,会返回失败,从而导致模块加载失败。
所以它的作用就是保证模块调用环境的 Perl 版本。

our 和 my 一样,都是对变量的声明,
不过 our 声明的是包全局变量,
而 my 声明的是词法变量。

不过,经过 our 声明的变量,它会变得像一个词法变量一样,
其实这也是 our 存在的目的:用来欺骗 strict pragma,使 strict 以为它是一个词法变量,其实却不是。

有一个简单的办法可以理解 our:
1,你就把 our 声明的变量和 my 声明的当成一样。
2,记住 our 和 my 的区别:our 声明的是一个包全局变量,因此在符号表中存储(可以通过全限定在任何地方访问),而 my 声明的是一个真正的词法变量,只能在闭合块中访问。


 flw 回复于:2005-06-05 19:45:21

my 和 our 的区别:
D:\MoChou>cat ttt.pl

use strict;

my $var;
$var = 1;
{
    my $var;
    $var = 2;
    print $var, "\n";
}
print $var, "\n";

D:\MoChou>ttt
2
1

D:\MoChou>

D:\MoChou>cat ttt.pl

use strict;

our $var;
$var = 1;
{
    our $var;
    $var = 2;
    print $var, "\n";
}
print $var, "\n";

D:\MoChou>ttt
2
2

D:\MoChou>


[ 本帖最后由 flw 于 2006-6-17 11:39 编辑 ]


 flw 回复于:2005-06-05 19:46:32

很显然,两处 my 声明的虽然是同一个名字“$var”,但是他们是两个变量。
而 our 却是同一个变量。


 flw 回复于:2005-06-05 19:50:27

再举一个例子,更加明显:
D:\MoChou>cat ttt.pl

use strict;

{
    my $var;
    $var = 2;
    print $var, "\n";
}

if ( defined $main::var ){
    print '$main::var defined! value = ', "$main::var.\n";
}
else{
    print '$main::var not defined!', "\n";
}

D:\MoChou>ttt
2
$main::var not defined!

D:\MoChou>

D:\MoChou>cat ttt.pl

use strict;

{
    our $var;
    $var = 2;
    print $var, "\n";
}

if ( defined $main::var ){
    print '$main::var defined! value = ', "$main::var.\n";
}
else{
    print '$main::var not defined!', "\n";
}

D:\MoChou>ttt
2
$main::var defined! value = 2.

D:\MoChou>


[ 本帖最后由 flw 于 2006-6-17 11:39 编辑 ]


 flw 回复于:2005-06-05 20:00:39

其实,our 的出现有它的历史,
Perl 和别的语言不同,可以随便声明变量,
在 Perl 4 那个时代,根本就不需要 my 什么的,
随便写个名字,就是变量了。
在 Perl 5 中仍然如此,除非你用 my 明确声明为词法变量,否则所有的变量都是(包)全局变量,而且可以不声明直接使用。
但是,这样有个坏处,那就是万一不小心写错名字了,或者解符号引用的时候,字符串运算错了,都会造成很多麻烦(因为按照 Perl 5 语法,这些都是正确的,其结果就是产生一个新的变量,很显然,这不是你想要的目的。)

所以,为了解决这些问题,在 Perl 5 中就引入了 strict 和 warnings 两个 pragma,它们的作用,就是限制变量不声明直接使用,
经过 strict 和 warnings 限制后,所有没有声明的直接使用的变量都会报错。但是 my 声明的变量又是局部变量,local 又不能创造变量,
所以,我们就没法使用全局变量了(注1),
因此就又引入了 our,our 的作用就是声明一个全局变量,但是让 strict 和 warnings 以为它是词法变量,因此 our 声明的变量也是词法作用域的。但是实际上它是全局变量。

注1:
如果不使用 our,我们有两种办法可以创建全局变量:
1,用 no strict "vars" 临时关掉 strict pragma,声明完了再用 use strict "vars" 打开。
2,用变量的全限定名称,如 $main::var 或者 $foo::bar 这样子。


 flw 回复于:2005-06-05 20:01:38

声明:
以上提到的“全局变量”这个字眼都表示“包全局变量”。


 happig1 回复于:2005-06-05 21:22:49

小弟看完后,收获颇多,谢谢各位.


 m0925j 回复于:2005-06-06 14:01:17

我原来以为在一个package里面定义了一个our变量,然后在一个pl里面use的话就能用pm里面那些our变量了,原来our只是相当于一个没在{}里面的my,这样理解对吗


 flw 回复于:2005-06-06 14:44:42

to m0925j:
不对,our 和 my 有本质的区别。our 声明的是包全局变量,my 声明的是词法变量。

use
package
our
三者之间无任何关系。


 flw 回复于:2005-06-06 15:00:47

use 是加载一个 .pm 文件,
package 是切换当前名字空间,
our 是在当前名字空间中创建一个变量,如果该变量已经存在,则 our 只起到一个声明的作用。


 m0925j 回复于:2005-06-06 15:34:19

我的意思是如果在一个package TTT里面定义一个our $good或者一个不带my也不带our的$good,然后要在另外一个pl里面引用这个good的话都需要use TTT;然后$TTT::good这样子吧?
另外如果一个my $good定义在文件的开头也没在任何{}里面,应该是跟our一样的吧?
如果没说清楚别骂我,同情我就好~~~~~~~~


 flw 回复于:2005-06-06 15:43:56

你还是没有明白 our 和 my 的区别。
our (或者什么修饰都没有)声明的是“包全局变量”,它的是“依附”在“包”上面的,它的存储位置是“包符号表”,
my 声明的是“词法变量”,它是“依附”在“代码块”上的,它的存储位置是“代码块”的“变量标签薄”,所以词法变量不可以从代码块之外访问(除了传递引用)。
但是包全局变量就不同了,用全限定就可以访问。


 m0925j 回复于:2005-06-06 15:51:53

了解~~~~




原文链接:http://bbs.chinaunix.net/viewthread.php?tid=556778
转载请注明作者名及原文出处