如何在perl的本地范围内访问导入模块中的变量?

时间:2017-01-26 18:27:37

标签: perl moose perl-exporter

我在创建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,因为它是由其他人拥有/使用的,我可以使用它:(

2 个答案:

答案 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)),这将导入变量到您的命名空间。

现在,在回答了你的问题之后,我将和其他人一起建议导出变量是一种非常糟糕的代码味道,并且可能不是最好/最干净的方式来做你想要的。