我什么时候应该使用“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
作为属性。
现在,如果我在 M1
中取消注释 use M2;
,我的 Eclipse 就会发疯。我想这是因为这是由“循环使用”创建的循环。
我评论了这个 use
,一切似乎都工作正常(我认为......),但让我真的很焦虑(我正在使用一个没有 use
-ing 其类的对象这“合法”吗?..)。这也让我想知道:
什么时候我真的需要使用
use
?我认为我被教导要始终使用它,尤其是当我使用对象时。当两个模块相互使用时,是否存在根本性错误(从某种意义上说,每个模块都使用另一个模块的对象;我知道在某些情况下,这在逻辑上是不可能的,但有时 - 就像在这种情况下 - 我认为它确实有道理)。
As long as I can remember, whenever I use a module I include a use
line at the beginning of my code.
Recently I was writing two Moose object modules that use each other. Look at this over-simplistic example:
One module:
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;
Another module:
package 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;
And a short example that uses them:
use strict;
use warnings;
use 5.010;
use M1;
use M2;
my $m1 = M1->new(name => 'dave');
say $m1->very_cool_name();
Now, note the two modules use each other. M1
creates an instance of M2
and use it to generate very_cool_name
, while M2
has an instance of M1
as an attribute.
Now, if I uncomment use M2;
in M1
my eclipse goes mad. I guess it's because this a the loop created by this 'circular use`.
I commented this use
and everything seems to works fine (I think...), but makes me really anxious (I'm using an object without use
-ing its class! Is that 'legal'?..). This also which made me wonder:
When do I really need to use
use
? I think that I was taught to always use it, and surely when I use an object.Is there anything fundamentally wrong when two modules use each other (in the sense that each uses an object of the other module; I know there some cases where this is logically impossible, but sometimes - as in this case - I think it does make sense).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
从 Perl 的角度来看,这很好。
use
足够聪明,可以识别模块已经加载并且不会再次加载。也就是说,淡淡的代码味道应该让您思考相互依赖是否可以接受,或者是否应该重构代码以消除它。日食显然没有那么明亮。注释掉其中一个
use
语句来安抚编辑器可能会起作用,但可能会产生微妙的错误,具体取决于模块加载的顺序(由应用程序)以及它们的加载时间。使用彼此的功能。例如,如果首先加载 M1,没有使用 M2
,并且有一个需要 M2 功能的BEGIN
块...繁荣!如果直到运行时(这很可能)没有发生任何事情,你应该没问题。虽然这不是问题,但如果您
使用
从其他包导入的符号,也会遇到问题。在这种情况下,如果不更改代码以完全限定所有引用,则无法删除use
。 (例如,调用MyModule::function()
而不仅仅是function()
)From a Perl perspective it's fine.
use
is smart enough to recognize that a module has already been loaded and not load it again. That said, the faint whiff of code smell should make you think about whether mutual dependency is acceptable or if you should refactor your code to eliminate it.Eclipse, apparently, is not quite as bright. Commenting out one of the
use
statements to placate the editor will probably work but could create subtle bugs depending on the order the modules are loaded in (by the application) and when they use each others functionality. e.g. if M1 were loaded first, didn'tuse M2
, and had aBEGIN
block that needed functionality from M2... boom! If nothing happens until runtime (which is likely) you should be okay.While it isn't an issue here, you'd also have problems if your
use
imported symbols from the other package. In that case couldn't remove theuse
without changing your code to fully qualify all references. (e.g. callMyModule::function()
instead of justfunction()
)M2 没有理由
使用 M1
。您实际上没有递归依赖关系。M2 所做的只是验证某个对象的类名(这不需要加载 M1)并调用它的方法(这意味着无论谁构建该对象都加载了 M1)。
您关于需要
使用
类才能调用该类的对象上的方法的规则是错误的。当您要直接调用类的方法时,使用
类 - 例如,new
。 (显然,这假设纯面向对象模块,而不是导出函数/符号的东西。)考虑多态性。这是一个功能,我可以创建自己的 M1 子类(例如,称为 M1A)并将其传递给 M2,而 M2 不必知道 M1A 的存在。
There's no reason for M2 to
use M1
. You don't actually have a recursive dependency.All M2 does is validate some object's classname -- which doesn't require having loaded M1 -- and call a method on it -- which means whoever constructed that object loaded M1.
Your rule about needing to
use
a class in order to call methods on an object of that class is wrong.use
a class when you're going to call methods on the it directly -- for example,new
. (This assumes pure OO modules, obviously, not things that export functions/symbols.)Consider polymorphism. It is a feature that I can make my own subclass of M1 (called, say, M1A) and pass it to M2 without M2 having to know anything about the existence of M1A.