示例代码:
m1.pm
my $a;
my $b;
sub init {
$a = shift;
$b = shift;
}
sub printab {
print "a = -$a-\n";
print "b = -$b-\n";
}
1;
m2.pm
my $a;
my $b;
sub init {
$a = shift;
$b = shift;
}
1;
test.pl
use strict;
use warnings;
use m1;
use m2;
init('hello', 'world');
printab();
执行命令
$ perl test.pl
a = --
b = --
$
如果init('hello', 'world')
调用已映射到m2.pm
并初始化变量($a
和$b
),那么会发生什么。
这种说法很有道理,但我不明白为什么test.pl
中没有这些值。
我在这里尝试做的事情有根本错吗? 使用具有相同命名子例程和变量的两个模块的正确方法是什么?
Perl use
的工作原理是什么?如果有人可以将它与C的#include
指令进行对比,那将会有所帮助。
答案 0 :(得分:13)
在Perl中,use
关键字与以下内容完全等效:
use Mymodule;
#is the same as
BEGIN {
require Mymodule;
Mymodule->import();
}
因此,如果您没有在代码中定义导入例程(或继承自Exporter
),那么您的模块不会将任何内容导入test.pl
正如Sinan捕获的那样,你没有在你的模块中声明一个包,所以它们默认为main
包。在这种情况下,所有子例程都在main
中,但是词法变量(用my
声明)仅限于它们声明的文件。
因此,m1
定义了词sub init
和sub printab
所在的$a
和$b
。但是当test.pl
加载m2
时,init
例程会被新定义覆盖,而新定义不再围绕两个词汇关闭。所以它写入包变量$main::a
和$main::b
而不是printab
绑定的词汇。
如果您启用了警告(学习时总是应该这样做),您会收到有关子程序重新定义的警告。
您应该使用以下命令启动每个模块:
package Some::Package::Name;
use warnings;
use strict;
然后以:
结束每个模块1;
这是因为当你use/require
一个模块时,它需要在结尾返回一个真值,以便Perl知道它已正确加载。
答案 1 :(得分:8)
首先,请阅读perldoc perlmod。
您不会在任一模块中声明命名空间,因此所有内容都位于main
命名空间中。在package m1;
和m1.pm
中package m2;
声明m2.pm
。
至少,您应该实现import
方法(或继承Exporter
提供的方法),以便使用模块的程序可以决定从哪里导入。
在我看来,你正在探索OO的边缘。
此外:
避免使用$a
和$b
作为变量名,因为很容易将它们与$a
使用的包变量$b
和sort
混淆}。
不要使用小写模块名称:它们是为pragmata保留的。
最小的实现(所有在一个文件中以便于测试)如下所示:
package My::M1;
use strict; use warnings;
sub new { my $class = shift; bless { @_ } => $class }
sub a {
my $self = shift;
my ($v) = @_;
$self->{a} = $v if @_;
return $self->{a};
}
sub b {
my $self = shift;
my ($v) = @_;
$self->{b} = $v if @_;
return $self->{b};
}
package My::M2;
use strict; use warnings;
use base 'My::M1';
sub printtab {
my $self = shift;
for my $x (qw(a b)) {
printf "%s = -%s-\n", $x, $self->$x;
}
}
package main;
my $m = My::M2->new(a => 'hello', 'b' => 'world');
$m->printtab;
答案 2 :(得分:2)
printab()
在文件m1.pm
中定义,只能访问作用于该文件的$a
和$b
变量。 $a
中的变量$b
和m2.pm
的范围限定为该文件,它们是不同的变量而不是$a
和$b
在m1.pm
。
init()
设置m2.pm
范围内的变量(因为这是定义&init
函数的最后位置)所以它没有设置printab()
将成为相同的变量试图打印。