示例代码:
m1.pm
my $a;
my $b;
sub init {
$a = shift;
$b = shift;
}
sub printab {
print "a = -$a-\n";
print "b = -$b-\n";
}
1;
Run Code Online (Sandbox Code Playgroud)
m2.pm
my $a;
my $b;
sub init {
$a = shift;
$b = shift;
}
1;
Run Code Online (Sandbox Code Playgroud)
test.pl
use strict;
use warnings;
use m1;
use m2;
init('hello', 'world');
printab();
Run Code Online (Sandbox Code Playgroud)
跑:
$ perl test.pl
a = --
b = --
$
Run Code Online (Sandbox Code Playgroud)
会发生什么是init('hello', 'world')调用映射到m2.pm并初始化变量($a和$b).
这种做法很有意义,但我不明白为什么这些价值观无法获得test.pl.
我试图在这里做一些根本性的错误吗?使用具有相同命名子例程和变量的两个模块的正确方法是什么?
Perl究竟是如何use工作的?如果有人可以将它与C的#include指令进行对比,那将会有所帮助.
Eri*_*rom 13
在Perl中,use关键字完全等效于以下内容:
use Mymodule;
#is the same as
BEGIN {
require Mymodule;
Mymodule->import();
}
Run Code Online (Sandbox Code Playgroud)
因此,如果您没有在代码中定义导入例程(或从中继承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;
Run Code Online (Sandbox Code Playgroud)
然后结束每个模块:
1;
Run Code Online (Sandbox Code Playgroud)
这是因为当你use/require是一个模块时,它需要在最后返回一个真值,以便Perl知道它正确加载了.
首先,阅读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;
Run Code Online (Sandbox Code Playgroud)