2010-10-22 180 views
2

只要我记得,每当我使用模块时,我都会在代码的开头添加一行use什么时候应该使用`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?我认为我被教导要始终使用它,当然,当我使用一个对象时。

  • 有什么根本性的错误,当两个模块相互利用(在这个意义上,每个使用其他模块的对象;我知道有一些情况下,这在逻辑上是不可能的,但有时 - 在这种情况下 - 我认为它确实有道理)。

回答

2

M2没有任何理由来use M1。您实际上没有递归依赖关系。

所有的M2都会验证某个对象的类名 - 它不需要加载M1 - 并调用其上的方法 - 这意味着构造该对象的任何人加载M1。

您的规则需要use一个类来调用该类的对象的方法是错误的。 use一个类,当你打算直接调用它的方法 - 例如,new。 (显然,这是假设纯粹的OO模块,不是导出函数/符号的东西。)

考虑多态性。这是一个功能,我可以让我自己的M1的子类(称为,M1A),并将其传递给M2,而M2不必知道有关M1A的存在。

+0

假设我正在将存储的M1对象检索到'$ m1'中。据我的理解,我不需要'使用M1'。那么,perl只需在我的'@ INC'中查找'M1.pm'来查看它应该如何处理这个加载的对象呢? – 2010-10-22 15:27:31

+0

*当你打算直接调用它的方法时使用''类''例如'new' * - 注意''M1'不用'使用M2'调用'M2-> new'。它似乎工作,那么在这里添加'use'有什么好处? – 2010-10-22 15:37:42

+1

@David:关于第二个问题,如果'M2'已经加载,那么'use M2'什么也不做(假设M2没有输出,如果它是OO类,它不应该输出)。但是在你尝试使用M2-> new之前,你必须已经加载了'M2'。 – Ether 2010-10-22 16:15:18

3

从Perl的角度来看,它很好。 use非常聪明,可以识别模块已经加载并且不会再次加载。也就是说,微弱的代码味道应该让你考虑相互依赖是否可以接受,或者如果你应该重构你的代码来消除它。显然,Eclipse不太明亮。注释use语句之一以安抚编辑器将可能工作,但可能会创建微妙的错误,具体取决于模块加载(通过应用程序)的顺序以及它们何时使用其他功能。例如如果M1首先被加载,没有use M2,并且有一个需要M2的功能的BEGIN块......繁荣!如果什么都没有发生,直到运行时(可能),你应该没问题。

虽然这不是一个问题,但如果您的use从其他软件包中导入了符号,您也会遇到问题。在这种情况下,如果不更改代码以完全限定所有引用,则无法删除use。 (例如,拨打电话MyModule::function()而不是function()

相关问题