日向夏特殊応援部隊

俺様向けメモ

around, BUILD, MooseX::Object::Pluggable のメモ

私的なメモです。

around

before, after, augment の汎用版かつ、引数や戻り値を変更出来るのがaround
before っぽく使う場合は、

around 'run' => sub {
  my $orig = shift;
  my ($self, @args) = @_;
  ### process before run
  ### ここになんか書く
  $orig->($self, @args);
};

みたいに書く。特徴的なのは第一引数に元のCodeRefが入ってる所。なんでオリジナルを呼び出す際に、$orig->($self, @args) のように書く。
また$origの呼び出しを明示的に書けるので、当然渡してる引数を操作すれば元のメソッド呼び出しに反映されるし、戻り値に関しても同じように操作出来る。つまり、

around 'calc' => sub {
  my $orig = shift;
  my ($self, @args) = @_;
  my $result = $orig->($self, @args);
  return $result * 1.05;
};

と言う Role を作って with すると、calcの計算結果は本来の計算結果に1.05倍した物が取れる。

BUILD

ほぼコンストラクタとして考えて良い。但し単なるプロパティの初期化なら default ないしは builder を使う。

package BuildSample;
use Moose;
use Perl6::Say;
use Data::Dump qw(dump);

has 'foo' => ( is => 'rw', isa => 'Int', required => 1, builder => 'init_foo' );
has 'bar' => ( is => 'rw', isa => 'Str', default => sub { say("init bar"); return ""; } );

sub init_foo {
    my $self = shift;
    say("init foo");
    $self->foo(12);
}

sub BUILD {
    my ($self, $args) = @_;
    say "[BUILD args] " . dump $args;
}

__PACKAGE__->meta->make_immutable;

package main;
use Perl6::Say;

my $sample1 = BuildSample->new( foo => 1, bar => "hoge" );

say("-" x 20);

my $sample2 = BuildSample->new();

BUILD の第二引数に new で渡したパラメータがハッシュリファレンスとして格納されてるみたい。

MooseX::Object::Pluggable

このモジュールの使い道は g:dann:id:dann さんお勧めの Devel::REPL を見るのが手っ取り早い。
そもそも MooseX::Object::Pluggable のやってる事ってのは、こんなソースですぐに分かると思う。

#!/usr/bin/perl

package Foo;

use Moose;
use Perl6::Say;
with 'MooseX::Object::Pluggable';

sub run {
    say("run");
}

package Foo::Plugin::BeforeAction;

use Moose::Role;
use Perl6::Say;

around 'run' => sub {
    my $orig = shift;
    my ($self) = @_;
    say("BeforeAction");
    $orig->($self);
};

package main;

use Perl6::Say;
use Data::Dump qw(dump);

my $foo = Foo->new;
$foo->load_plugin("+Foo::Plugin::BeforeAction");
$foo->run;

プラグインは Role として定義しておき、load_plugin ってのはこの例では、Foo に with 'Foo::Plugin::BeforeAction' するのと同じ事。$foo->meta->roles で確認出来る。