我已经很久没有用 Perl 编写任何代码了。现在我又开始编写代码了,在单个“.pm”文件中编写两个包时遇到了一个有趣的情况。到目前为止,我认为如果我在一个文件中定义两个包(例如 ConfigData 和 RuntimeData),我可以为每个包定义一个具有相同名称(例如 my $instance)的变量(用“my”声明),而不会发生冲突。作为示例,下面是一段最简洁的代码来说明这一点:
package Jabs::ConfigData;
use strict;
use warnings;
my $instance;
sub new {
my ($class) = @_;
unless (defined $instance) {
$instance = bless {}, $class;
}
return $instance;
}
1; # End of 'ConfigData'
package Jabs::RuntimeData;
use strict;
use warnings;
my $instance;
sub new {
my ($class) = @_;
unless (defined $instance) {
$instance = bless {}, $class;
}
return $instance;
}
1; # End of 'RuntimeData'
我调用了 perl -c test2.pm 并收到以下消息作为反馈:
"my" variable $instance masks earlier declaration in same scope at test2.pm line 27.
test2.pm syntax OK
现在我不清楚为什么范围应该相同。因为'我的 $instance 是在两个不同的包中定义的。我使用的是 Ubuntu 24.04 LTS 和 Perl5(修订版 5 版本 38 颠覆版 2)
有人能为我解释一下我的理解问题吗?
相关的perldoc -f my说:
形式的 package 关键字
package NAME
不包含这样的范围。尽管 package 的文档提到你可以使用块声明包,例如package NAME BLOCK
。下面是我对此类块的演示。perldoc perlmod详细说明:
输出:
简而言之,包变量和词法变量是两个独立的变量跟踪系统,彼此之间没有任何关系。
包变量实际上是全局变量。只要您知道完全限定的包名称(例如
main::foo
),它就会存在于程序中的所有时间和位置。该package
语句仅更改要使用的默认包。local
临时替换范围(包含块或文件)中包变量的值。词法变量完全由包含声明()的范围(包含块或文件)控制
my
。就您而言,两个实例都
my $instance
出现在同一范围(文件)中。但是,看起来您正在尝试创建两个单例类,您可以在其中返回已经创建的东西或在第一次使用时创建它。
Perl v5.10
state
允许您将该变量移入子例程。这是一个持久词汇变量。而且,//
(定义或)允许您使用二进制赋值来简化事情:在 v5.10 之前,您可以通过
new
在包含 的范围内定义 来执行相同的操作$instance
。现在$instance
仅存在于该范围内: