使用 Moose 程式設計/難點/Moose 與 Moose
外觀
在使用 Moose 一段時間後,你最終會發現自己擁有了一系列想要重複使用的類。不幸的是,Moose 不會讓在 Moose 內部使用這些 Moose 類變得容易。以下是在 Moose 內部執行的一些困難任務[1]。
在這些示例中,MooseObj 是一個 Moose 物件。
- isa => ArrayRef[ MooseObj ]
- 沒有語法糖來方便建立 MooseObj。
- 無法從
$self->MooseObj( [{constructor_args1}, {constructor_args2}] )輕鬆強制轉換。
- isa => 'MooseObj'
- 沒有對 MooseObj 的語法自動裝箱,你不能執行以下操作:
$self->foo->new( {constructor_args} )。 - 沒有隱式方法繞過 MooseObj 的建立並設定其訪問器。更多資訊請參見 一對一自動構建。
- 沒有對 MooseObj 的語法自動裝箱,你不能執行以下操作:
如果你不關心 MooseObj,只關心內部的訪問器怎麼辦?子物件可能只是作為更多訪問器的邏輯分組,如以下示例所示。
package Address;
use Moose;
has 'street' => ( isa => 'Str', required => 1, is => 'ro' );
has 'city' => ( isa => 'Str', required => 1, is => 'ro' );
has 'zip' => ( isa => 'Str', required => 1, is => 'ro' );
has 'state' => ( isa => 'Str', required => 1, is => 'ro' );
package USProfile;
use Moose;
has 'workAddress' => ( isa => 'Address', is => 'ro' );
has 'homeAddress' => ( isa => 'Address', is => 'ro' );
即使 Moose 非常努力地替換和抽象掉許多 Perl 的基本型別,這裡與使用 Address 雜湊相比,它使工作變得困難。以下是一些明顯的困難。
- 你不能跳過建立新Address物件
- 語法
$USProfile->workAddress->street('1234 FooStreet')無效。 - 語法
$USProfile->workAddress->{street} = '1324 FooStreet'將是有效的(假設workAddress是雜湊)。
- 語法
- 你可能希望元件類Address要求其子屬性,但沒有辦法在該類用作另一個類的子類時,停用這些
requires=>1。- 語法
has 'workAddress' => ( isa => 'Address', is => 'ro', default => sub{Address->new} );無效。 - 由於與
is=>'ro'類似的問題,這在這個情況下並不十分有用。
- 語法
本節正在重寫 現在顯然應該發生一些漂亮的事情來方便建立電子郵件。在這裡進行的任何工作都會極大地促進 Moose 在基於令牌的系統中的應用,例如 XML,你可以在 Moose 中輕鬆地建模一個一級樹,然後將其拉入另一個 Moose 類以建立多級文件。以下是尚未實現的虛擬碼。
my $person = USProfile->new;
## Hack a handles new into the Email code, which calls its own constructor
my $email = $person->email->new({ (constructor) })
## Still permit some sort of construction that suffices the required
## obviously a no-go if you have it embedded in an ArrayRef or HashRef
my $person => USProfile->new({state=>'TX', email=>{[moose_args=>]constructor args} }
可能需要為繼承自 Moose::Object 的事物設定一組 AttributeHelpers。
另一種實現此目的的方法類似於(由 steven 提供)。
has hash => (
is => "ro"
, default => sub { blessed(shift)->new }
, lazy => 1
);
my $h = Hash->new;
$h->hash->hash->hash;
print $h->dump;'
這裡有一些問題。
blessed(shift)->new應該是isa=>的值。- 它不適用於
isa,這些isa有required=>1,必須有一些方法自動構建,或者傳送建構函式引數。
- ^ 困難或過於冗長。