只要我记得,每当我使用模块时,我都会在代码的开头添加use
行。
最近我写了两个相互使用的Moose对象模块。看看这个过于简单的例子:
一个模块:
package M1 0.001;
use Moose;
use 5.010;
use namespace::autoclean;
# use M2; ### SEE QUESTION BELOW
has 'name' => (
is => 'ro',
isa => 'Str',
required => 1,
);
has 'very_cool_name' => (
is => 'ro',
lazy => 1,
builder => '_build_very_cool_name',
);
sub _build_very_cool_name {
my ($self) = @_;
my $m2 = M2->new( m1 => $self );
return 'very ' . $m2->cool_name();
}
__PACKAGE__->meta->make_immutable;
1;
另一个模块: 包M2 0.001;
use Moose;
use 5.010;
use Data::Dumper; # TODO DEBUG REMOVE
use namespace::autoclean;
use M1;
has 'm1' => (
is => 'ro',
isa => 'M1',
required => 1,
);
sub cool_name {
my ($self) = @_;
return 'cool ' . $self->m1->name();
}
__PACKAGE__->meta->make_immutable;
1;
一个使用它们的简短例子:
use strict;
use warnings;
use 5.010;
use M1;
use M2;
my $m1 = M1->new(name => 'dave');
say $m1->very_cool_name();
现在,请注意这两个模块互相使用。 M1
创建M2
的实例并使用它生成very_cool_name
,而M2
的实例为M1
作为属性。
现在,如果我在use M2;
取消注释M1
,我的日食会发疯。我想这是因为这是一个循环使用的循环。
我评论了这个use
,一切似乎都很好(我想......),但让我非常焦虑(我正在使用一个没有use
的对象 - 它的类!是的'法律'?..)。这也让我想知道:
我何时才需要使用use
?我认为我被教导要经常使用它,当然我使用的是对象。
当两个模块互相使用时(从某种意义上说,每个模块都使用另一个模块的对象),是否有任何根本错误;我知道在某些情况下这在逻辑上是不可能的,但有时 - 在这种情况下 - 我认为这确实有意义。)
答案 0 :(得分:3)
从Perl的角度来看,没关系。 use
足够聪明,可以识别模块已经加载而不再加载。也就是说,微弱的代码气味应该会让你思考相互依赖是否可以接受,或者你是否应该重构你的代码来消除它。
use
语句来安抚编辑器可能可以工作,但可能会产生微妙的错误,具体取决于模块加载的顺序(由应用程序)以及何时使用彼此功能。例如如果首先加载M1,则不use M2
,并且有BEGIN
块需要M2的功能......繁荣!如果在运行之前没有任何事情发生(可能),你应该没问题。
虽然这不是问题,但如果您从其他包中导入use
符号,也会遇到问题。在这种情况下,无法删除use
而不更改您的代码以完全限定所有引用。 (例如,请致电MyModule::function()
而不是function()
)
答案 1 :(得分:2)
M2没有理由use M1
。你实际上没有递归依赖。
所有M2都会验证某个对象的类名 - 它不需要加载M1 - 并在其上调用一个方法 - 这意味着构造该对象的任何人都加载了M1。
关于为了在该类的对象上调用方法而需要use
类的规则是错误的。当你要直接调用方法时,use
一个类 - 例如new
。 (这假定纯OO模块,显然不是导出函数/符号的东西。)
考虑多态性。这是一个特征,我可以创建我自己的M1子类(称为M1A)并将其传递给M2,而不需要知道有关M1A存在的任何信息。