4

例子

out.pl:

(my|our|local|global|whatever???) var = "test";
require("inside.pm");

里面.pm:

print $var;

我不想使用包 - 它压倒了我的需求 :) 谢谢!

4

2 回答 2

5

总是在使用一个包,即使你不使用package声明。默认情况下,您正在使用 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要好得多。

至少,你知道价值从何而来。它来自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 中很容易做一些非常非常糟糕的想法,但是使用包并不需要太多的工作,所以它只是变成了一个糟糕的想法。而且,如果您开始学习一点面向对象的 Perl,您实际上可以不费力气地以完全正确的方式完成所有操作。

选择权在你。请记住,您拍摄的脚可能是您自己的。

于 2011-09-25T04:49:24.670 回答
4

它将与our.

$ cat out.pl
our $var = "test";
require("inside.pm");

$ cat inside.pm 
print "Testing...\n";
print "$var\n";

$ perl out.pl
Testing...
test

这是有效的,因为our它是$var全局的,并且inside.pm正在$var定义的范围内执行。不确定这是推荐的技术,但这是一个有趣的问题!

编辑:需要根据评论澄清(好的补丁)答案:

Perl 函数的文档中our

our将简单名称与当前包中的包(读取:全局)变量相关联,以便在当前词法范围内使用。换句话说,具有与orour相同的范围规则,但不一定创建变量。mystate

所以使用our,我们得到$var了当前的包(这里可能是main),我们可以在它的范围内使用它。实际上,它对于您需要的文件中的代码是“全局的”。

没有 , 引入了真正的全局our变量,因为变量默认为全局变量。但我不知道有谁会推荐他们。

于 2011-09-24T22:00:32.663 回答