2013-08-30 27 views
4

我想在方法修飾符之前應用一個Moose'我的類中的多個方法。我想在角色中提供修飾符方法。我能做到這一點有點像這樣:如何將Moose方法修飾符應用於基於方法屬性的方法?

package MyApp::Role; 

use Moose::Role 

before [qw(foo bar)] => sub { 
    ... 
}; 

package MyApp; 

use Moose; 
with (MyApp::Role); 

sub foo { ... } 

sub bar { ... } 

sub baz { ... } # this method is unaffected 

但是,需要維護的作用有關方法列表它關係到消費類,只是似乎是錯誤的。我願做它更聰明的辦法,像法屬性:

package MyApp; 

use Moose; 
with (MyApp::Role); 

sub foo :SomeFlag { ... } 

sub bar :SomeFlag { ... } 

sub baz { ... } # this method is unaffected 

我不熟悉如何識別方法屬性或我怎麼會動態地應用方法修飾他們。

或者,也許有這樣做的更好的辦法?

+0

你知道如何實現方法的屬性? (請參見[屬性](https://metacpan.org/module/attributes))。上次我看,這是一個絕對痛苦。但我必須承認,它使得界面美觀。 – amon

回答

5

讓我們用Attribute::Handlers此 - 一個相當明智的方式使用屬性。我們必須在基類中定義一個函數,它本身具有:ATTR(CODE)屬性。這需要許多參數:

  1. 其中子(或其他變量)來自的包。
  2. 甲globref或字符串ANON
  3. 對值的引用(here:coderef)。
  4. 屬性的名稱。
  5. 屬性的可選數據。
  6. 該屬性被調用的(編譯)階段。
  7. 聲明子文件名。
  8. 聲明子的行號。

所以我們所能做的就是編寫一個應用一個before處理:

use strict; use warnings; use feature 'say'; 

BEGIN { 
    package MyRole; 
    use Moose::Role; 
    use Attribute::Handlers; 

    sub SomeFlag :ATTR(CODE) { 
     my ($package, $globref, $code, $attr, $data, $phase, $filename, $line) = @_; 

     ref($globref) eq 'GLOB' 
      or die "Only global subroutines can be decorated with :SomeFlag" 
        . " at $filename line $line.\n"; 

     # use the MOP to install the method modifier 
     $package->meta->add_before_method_modifier(
      *$globref{NAME} => sub { 
       warn "Just about to call a flagged sub!"; 
      }, 
     ); 
    } 
} 

BEGIN { 
    package MyApp; 
    use Moose; 
    # important: SomeFlag must be available before the attrs are handled (CHECK phase) 
    BEGIN { with 'MyRole' }; 

    sub foo :SomeFlag { say "Hi from foo sub!" } 
    sub bar :SomeFlag { say "Hi from bar sub!" } 
    sub baz   { say "Hi from baz sub!" } 
} 

package main; 

my $o = MyApp->new; 
$o->$_ for qw/foo bar baz/; 

我塞進了這一切到一個文件中,但很明顯時並不需要(剛加入所需use s)。

輸出:

Just about to call a flagged sub! at so.pl line 16. 
Hi from foo sub! 
Just about to call a flagged sub! at so.pl line 16. 
Hi from bar sub! 
Hi from baz sub! 
+0

非常好 - 謝謝! – cubabit

+0

您可以將'<! - language:lang-none - >'放在輸出代碼塊的上方,以防止語法突出顯示。 –

+0

Brad Gilbert:完成 – cubabit