2017-07-11 100 views
1

我是一個新的Perl。我試圖定義以下方式/使用類:使用別名與穆斯似乎不工作時聲明類

package A::B::C; 
use strict; 
use warnings; 
use Moose; 
use aliased 'A::B::D'; 
has 'attribute' => (isa => 'ArrayRef[D]', is => 'ro', required => 1); 

在創建一個對象:

use aliased 'A::B::C'; 
use aliased 'A::B::D'; 
my $aref = [D->new()]; 
C->new($aref); 

然而駝鹿抱怨失敗:

Attribute (attribute) does not pass the type constraint because: Validation failed for 'ArrayRef[D]' with value ARRAY(0x7f2b658b51c0) 

但是,如果我切換到不使用別名,它的工作原理(當然應該):

package A::B::C; 
use strict; 
use warnings; 
use Moose; 
use A::B::D; 
has 'attribute' => (isa => 'ArrayRef[A::B::D]', is => 'ro', required => 1); 

我的問題是爲什麼使用別名位不適用於Moose?

感謝

回答

1

駝鹿不知道use aliased。該編譯指示use aliased是Perl上的一個黑客;它所做的只是創建一個帶有短名稱的子例程,該短名稱返回類名稱。所以

use aliased 'A::B::D'; 

相當於

use A::B::D; 

sub D() { 'A::B::D' } 

(見aliased.pm#L45

然後,當你這樣說D->new(),Perl中注意到有一個名爲D子程序(常量)並解釋D作爲子程序調用,然後該方法調用結果。 (而不是像通常那樣將D解釋爲字符串常量)。即使對於Perl,D也不是真正的軟件包名稱;就像一個包名一樣!此外,Moose有自己的解析類型聲明的系統(這就是爲什麼你可以像你一樣給它們一個字符串)和它自己的全局的類型聲明的概念。沒有人知道aliased,因此Moose正在使用將未識別類型視爲(全局)包名的默認行爲。

如果您瞭解如何aliased的作品,你可以通過做

has 'attribute' => (isa => 'ArrayRef['.D.']', is => 'ro', required => 1); 

利用它,但它可能更好地記住

Type names are global throughout the current Perl interpreter

,要麼使用完全隨處可見類型限定的軟件包名稱,或使用Type::Tiny並編寫

package A::B::C; 

use Moose; 

use aliased 'A::B::D'; 

use Types::Standard qw/ ArrayRef /; 
use Type::Utils qw(class_type); 

has 'attribute' => (isa => ArrayRef[class_type D], is => 'ro', required => 1); 

(注意周圍D缺乏報價,儘可能use aliased只是因爲!)。

Type::Tiny可能會比Moose類型更快,所以您可能想要考慮它)。

+0

是標準/推薦使用短名稱進口的方式嗎?我想確定的是,我最終使用的方法沒有任何與此相關的陷阱,只是用作指定整個路徑的替代品。 – user2103008