您总是使用包,即使您不使用 package 声明。默认情况下,您在包 main 中工作。
您使用our 声明的所有变量都是包变量,应该在包范围内可用。这是一个例子:
#! /usr/bin/env perl
# test2.pl
use strict;
use warnings;
our $foo = "bar";
1;
由于$foo 被声明为包变量,它将在其他程序中可用:
#! /usr/bin/env perl
use strict;
use warnings;
require "test2.pl";
our $foo;
print "The value of \$foo is $foo\n";
现在我已经给了你足够多的绳子,我会告诉你不要用它上吊自己。
这是一个非常非常糟糕的想法。注意到$foo 从某种几乎不可能弄清楚的神秘机制中获取值了吗?
包太复杂?真的吗?没那么难!看这个例子:
#! /usr/bin/env perl
# test2.pm
package test2;
use strict;
use warnings;
our $foo = "bar";
1;
除了我添加了package 声明并且现在调用我的程序test2.pm 而不是test2.pl 之外,与以前没有太大不同。
这是我的访问方式:
#! /usr/bin/env perl
use strict;
use warnings;
use test2;
print "The value of \$foo from package test2 is $test2::foo\n";
我所要做的就是在变量中使用包名。这是一个BAD IDEA,但比上面显示的REALLY, REALLY BAD IDEA要好得多。 p>
至少,您知道价值的来源。它来自test2.pm。而且,如果您在子程序中设置它,您就可以访问该变量。
#! /usr/bin/env perl
# test2.pm
package test2;
use strict;
use warnings;
sub fooloader {
our $foo = "bar";
}
1;
注意$foo 是在子程序fooloader 中设置的。而且,这是我的另一个访问它的程序:
#! /usr/bin/env perl
use strict;
use warnings;
use test2;
&test2::fooloader();
print "The value of \$foo from package test2 is $test2::foo\n";
现在,您可以使用 Exporter 来导出您的子例程(甚至是变量),但这已经不是您看到太多的东西了。主要是因为它是一个非常糟糕的想法。不如原来的REALLY REALLY BAD IDEA,但比上面的BAD IDEA还要糟糕:
#! /usr/bin/env perl
# test2.pm
package test2;
use base qw(Exporter);
our @EXPORT = qw(fooloader);
use strict;
use warnings;
sub fooloader {
our $foo = "bar";
}
1;
现在,我可以在没有包名的情况下使用子程序fooloader:
#! /usr/bin/env perl
use strict;
use warnings;
use test2;
fooloader();
print "The value of \$foo from package test2 is $test2::foo\n";
当然,问题在于您不知道子例程fooloader 的来源。如果您使用@EXPORT_OK 而不是@EXPORT,则可以使用use test2 qw(fooloader); 并记录fooloader 函数的来源。它还将帮助您知道不要在自己的程序中创建自己的 fooloader 函数并覆盖您导入的函数。然后,想知道为什么您的程序不再有效。
顺便说一句,您还可以导出变量而不仅仅是函数。然而,这变成了一个真的、真的、真的很糟糕——没有什么可怕的想法,因为它违反了你首先使用包的所有理由。如果您要这样做,为什么还要麻烦包裹?为什么不简单地拿枪打自己的脚呢?
最好和首选的方法是使用面向对象的 Perl 并以 完全正确的方式 进行。一种让您确切知道发生了什么以及为什么的方式。而且,可以很容易地弄清楚你的代码在做什么。一种将错误降至最低的方法。
看看彻底面向对象的 Test2 类:
#! /usr/bin/env perl
# Test2.pm
package Test2;
sub new {
my $class = shift;
my $self = {};
bless $self, $class;
return $self;
}
sub FooValue {
return "bar";
}
1;
并使用 Test2 类:
#! /usr/bin/env perl
use strict;
use warnings;
use Test2;
my $tester = Test2->new;
print "The value of foo from package test2 is " . $tester->FooValue . "\n";
这是最好的方法,因为即使你使用包,你也可以操纵$test2::foo 的值,它会在你的整个程序中被改变。想象一下,如果这是 $constants::pi 并且您将它从 3.14159 更改为 3。从那时起,使用 $constants::pi 会给您错误的值。如果你使用面向对象的方法,你不能改变方法Constant->Pi的值。它将永远是 3.14159。
那么,我们今天学到了什么?
我们了解到,在 Perl 中很容易做一些非常非常糟糕的想法,但使用包并不需要太多工作,所以它只是一个BAD IDEA。而且,如果您开始学习一点面向对象的 Perl,您实际上可以不费吹灰之力地以完全正确的方式完成所有操作。
选择权在你。请记住,您拍摄的脚可能是您自己的。