2011-11-03 32 views
3

我有一個對象,它擁有一堆對象。該對象表示當前狀態,並且堆棧中的每個對象都保持特定嵌套級別的狀態。我如何使用鼠標委託給數組的第一個元素?

package State; 

use Mouse; 
use RealState; 

has state_stack => { 
    is => 'rw', 
    isa => 'ArrayRef[RealState]', 
    default => sub { 
     return [RealState->new] 
    } 
}; 

我想要州委託給State->state_stack->[0]。我怎樣纔能有效地與鼠標(所以沒有元黑客攻擊)。我不能使用穆斯,my project不能有任何依賴(我捆綁鼠標::小)。

「你不行」很好,我會寫一個AUTOLOAD

回答

3

你不能直接,但有一個比AUTOLOAD更好的黑客。也就是說,RealState-> meta-> get_all_method_names()爲您提供在RealState中定義的方法名稱。

#!perl 
use 5.14.0; 
package RealState { 
    use Mouse; 

    sub foo { 'foo' } 
    __PACKAGE__->meta->make_immutable; 
} 
package State { 
    use Mouse; 

    has stack => (
     is => 'rw', 
     isa => 'ArrayRef', 
     default => sub { [ RealState->new ] }, 
    ); 

    # define delegates for stack->[0] 
    my $meta = __PACKAGE__->meta; 
    foreach my $name(RealState->meta->get_all_method_names) { 
     next if Mouse::Object->can($name); # avoid 'new', 'DESTROY', etc. 

     # say "delegate $name"; 
     $meta->add_method($name => sub { 
      my $self = shift; 
      $self->stack->[0]->$name(@_); 
     }); 
    } 

    $meta->make_immutable; 
} 

my $state = State->new(); 
say $state->foo(); 
+0

謝謝!我更喜歡更動態的東西,堆棧中的其他元素可能是帶擴展名的子類的實例。我想我可以重新運行,每次我改變堆棧時,都不會經常發生。我必須刪除不可變的標誌。如果State-> can($ name)'需要'next? – Schwern

+0

更有活力!如果是這樣,AUTOLOAD是一個更聰明的方法。或者,如果我愛你,我會首先定義子$ {$ state-> stack - > [0]}並使用$ stack-> first-> foo(),這很簡單且有效。 –

相關問題