終於把這篇讀完喇!首先是List::MoreUtils模組的zip功能,是把兩個串列互相交錯生成串列3
值得注意的是若兩陣列數量不等則會插入一個undef的值。
然後就是搞得我暈頭轉向的這段喇
coerce 'Human::EyeColor' => from 'ArrayRef' => via { my @genes = qw'bey2_1 bey2_2 gey_1 gey_2'; return Human::EyeColor->new( zip(@genes, @{$_}) ) }; has 'eyeColor' => ( is => 'ro', isa => 'Human::EyeColor', coerce => 1, required => 1 ); |
coerce 的作用時機是當有個 Human::EyeColor 類的參數(?)正在被定義的時候,coerce 會把定義式給的參數給轉換成coerce 函式中的樣式。 也就是當code是長這樣:
has 'eyeColor' => ( is => 'ro', isa => 'Human::EyeColor', required => 1 ); |
在定義時必須要使用這樣my $test = Human->new( eyeColor => Human::EyeColor->new( ... ) );
而有了coerce,你可以直接給eyeColor這個屬性一個陣列參照,coerce會自動幫你new一個Human::EyeColor,如下面這行:
my $test = Human->new( eyeColor => [ qw/brown brown green green/ ] );當在設定eyeColor時,定義了一個Human::EyeColor 類的參數,因此coerce 就把你給的參數
[ qw/brown brown green green/ ] 給送進 via 中的副程式裡。
例子中很酷的是,經過zip後送出的eyeColor參數是
eyeColor => Human::EyeColor->new( bey2_1 brown bey2_2 brown gey_1 green gey_2 green )
然後在Human::EyeColor中又規定了coerce,再次把參數給轉換( 口才不好 )
coerce 'Human::Gene::bey2' => from 'Str' => via { Human::Gene::bey2->new( color => $_ ) }; coerce 'Human::Gene::gey' => from 'Str' => via { Human::Gene::gey->new( color => $_ ) };
has [ qw'bey2_1 bey2_2' ] => ( is => 'ro', isa => 'Human::Gene::bey2', coerce => 1 ); has [ qw'gey_1 gey_2' ] => ( is => 'ro', isa => 'Human::Gene::gey', coerce => 1 ); |
也就是變成了eyeColor => Human::EyeColor->new( bey2_1 => Human::Gene::bey2->new( color => brown ), .....)
最後overload '+' 就是定義了當該類的物件遇到運算式 + 的時候要做甚麼特殊處理
值得一提的是 $test + 1 的結果是一個undef的值,也就是只要該類物件遇到運算子 +
就會直接overload進副程式了,不會管被+的是不是該類的物件。