我在创建perl Moose模块时遇到困难。
我有一个全局pm模块。
package XYZ;
require Exporter;
our @ISA = qw(Exporter); ## EDIT missed this line
our @EXPORT_OK = qw($VAR);
my $VAR1 = 1;
our $VAR = {'XYZ' => $VAR1};
1;
我想在我正在创建的$VAR
模块中获取Moose
package THIS;
use Moose;
use YAML::XS;
sub get_all_blocks{
my ($self) = @_;
require $self->get_pkg(); # this returns the full path+name of the above package
# i cannot use use lib+use since the get_pkg starts complaining
our $VAR;
print YAML::XS::Dump($XYZ::VAR); # this works
print YAML::XS::Dump($VAR); # this does not work
# i cannot use the scope resolution since XYZ would keep changing.
}
1;
有人可以帮助我访问变量吗?
编辑:错过package XYZ
代码中的一行。
我无法触摸package XYZ
,因为它是由其他人拥有/使用的,我可以使用它:(
答案 0 :(得分:4)
导出变量可能很容易导致麻烦。
为什么不
package XYZ;
use strict;
use warnings;
use Exporter qw(import);
our @EXPORT_OK = qw(get_var);
our $VAR = '...';
sub get_var { return $VAR }
然后
package THIS;
use warnings;
use strict;
use XYZ qw(get_var);
my $var = get_var();
请参阅Exporter。
至于你想做什么,有两个问题。
$VAR
的 XYZ
永远不会导入THIS
。如果您需要其他包中的符号,则需要导入它们。这些包必须首先使它们可用,因此您还需要将它添加到@EXPORT_OK
。
因此,请使用上述内容,但使用$VAR
代替get_var()
。
另一种方法是使用@EXPORT
,然后将这些符号引入到use Package;
的每个程序中。我强烈建议仅在呼叫者需要明确列出他们想要的内容时使用@EXPORT_OK
。这也很好地记录了正在使用的内容。
即使你添加了它,在THIS
中仍然有一个同名的变量,它会隐藏(掩码,阴影)$XYZ::VAR
。因此,请移除our $VAR
中的THIS
。这是全局变量的一个问题的一个很好的例子。一旦你介绍它们,你必须要小心,即使只是命名变量。
但是跨模块共享变量存在更大的问题。
它使应用程序组件纠缠在一起,代码变得越来越难以使用。它违反了定义明确的范围和模块化设计的原则,它可以实现远距离的操作等.Perl为结构化代码提供了许多好的工具,我们很少需要全局变量和共享变量。它告诉Exporter
本身warns against that。
当然,可能需要或很好地使用它,并且偶尔可以在模块中找到它。但这是一个例外,可以谨慎而谨慎地使用。
答案 1 :(得分:1)
您不希望our $VAR;
的命名空间中有THIS
。这创建了对$THIS::VAR
的词汇引用。不是你想要的。
相反,您需要use
正确:
use XYZ qw($VAR);
但是,XYZ
没有import
在此处运行,因此您需要更新它。有两种方法可以修复XYZ
来执行此操作 - 一种是导入导入,例如use Exporter qw(import);
,另一种是导出Exporter
,例如use parent qw(Exporter);
。这两个都可以使XYZ->import(...)
正常工作。
XYZ
正确use
Exporter
后,use XYZ qw($VAR);
行将导致perl隐式加载XYZ并调用XYZ->import(qw($VAR))
,这将导入变量到您的命名空间。
现在,在回答了你的问题之后,我将和其他人一起建议导出变量是一种非常糟糕的代码味道,并且可能不是最好/最干净的方式来做你想要的。