2011-03-28 24 views
5

通常我會在課程結束時通過__PACKAGE__->meta->make_immutable進行彙編。然而,我應該在什麼時候讓一個不可變的類在運行時將其組合到自身中?我是否應該這樣做才能獲得更好的表現,或者這與make_immutable不兼容? make_immutable似乎加快了對象的實例化,但它是否在對象實例化後執行任何操作?當我真正使用 - > meta時,何時應該使Moose類不可變?

例如,沿着線的東西:

BUILD { 
    my $self = shift; 
    use Module::Load; 

    ### Use the arguments passed in to determine roles applicable to 
    ### this instance of the object. Load and apply roles. 
    for my $role ($self->_determine_roles()) { 
    load $role; 
    $role->meta->apply($self); 
    } 

    ### $self is now a Class::MOP::Class::__ANON__... anonymous class 
    ### Should I then be saying I'm done mutating it with something like this? 
    ### can make_immutable even be run on an object instance and not a package? 
    $self->meta->make_immutable; 
} 

即使上面的代碼適用於單一封裝中,當一個對象reblesses本身與'Foo'作用,產生一個匿名類會發生什麼,然後第二個對象用'Foo'祝福自己(成爲那個相同的匿名類)然後'Bar'的作用?當第二個對象自己加入到不可變的第一個匿名類中,然後嘗試將該角色應用於現在不可變的匿名類來創建一個新的匿名類時,它會正常工作嗎?

從閱讀有關Moose::Meta::Class的文檔,看起來只有一個類可以是不可變的,而不是對象的實例。如果是這樣,我應該忽略make_immutable,因爲我正在改變我的課程嗎?

回答

7

你應該像平常一樣在課堂上做make_immutable,而不用擔心你的BUILD

當您在運行時將角色應用於實例時,它不會修改實例的類以應用該角色(這將是混亂和可怕的並會影響該類的所有其他實例);它會創建一個新的匿名類,該類從您的類繼承並執行請求的角色,然後將該實例重新分配給該類。由於原始類沒有被修改,所以不存在是否是開放/可變的問題。

你實際上可以$self->meta->make_immutable角色應用程序後 - 它會使新創建的匿名類免疫 - 爲了完整性,你可能應該。但它只會帶來一點好處,因爲make_immutable所做的大部分工作是使構造函數更快,而新類的構造函數不會運行。

如果您想查看應用程序對實例的角色工作方式的詳細信息,您應該查看Moose::Meta::Role::Application::ToInstance的來源。

+0

即使當我將新的匿名類設置爲不可變時,它仍然創建另一個匿名類,它封裝了第一個不可變匿名類和新不可變角色,因此將角色應用於不可變匿名類仍然可以正常工作。得到它了! – Oesor 2011-03-28 18:04:27

相關問題