2010-10-22 198 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()

相關問題