下記ですが、Moose 0.65で直ってますよ!
MooseでRoleを作ります
package Role;
use Moose::Role;
requires 'foo';
no Moose;
で、このRoleをChildで実装しますが、こいつに親クラスParentがあると仮定します。こんな感じ。
# Parent
package Parent;
use Moose;
has 'foo' => ( is => 'rw', isa => 'Int' );
no Moose;
# Child
package Child;
use Moose;
extends 'Parent';
with 'Role';
no Moose;
で、foo()ってattributeがついているんだから、当然Roleのrequiresも満たしてると思いますよね? 満たしてません。
実はMoose::Roleのrequiresによって作成される制限はMoose自身のhasをrequiresの条件を満たす物として認識できないようです。これは既知。なので、以下のようにoverrideしてやる必要があります:
package Child;
use Moose;
extends 'Parent';
override 'foo' => sub { super() };
with 'Role';
no Moose;
ちなみにnew()で色々と魔法を追加したい場合はaroundを使うといいわけですが、ここにも落とし穴があります。先ほどのParentでaround newをしてみます
package Parent;
use Moose;
has 'foo' => ( is => 'rw', isa => 'Int' );
around 'new' => sub {
my ($next, $class, @args) = @_;
# なんかごにょごにょ・・・
return $next->($class, @args);
};
no Moose;
ChildはParentから継承しているんだから、Parent::new()およびそのaroundで指定された無名関数が呼ばれると思いますよね?ところがこのままではこのnew()は呼ばれません。
呼ばれるのはnew()から*明示的に*指定されたメソッドと、BUILDだけです。なので、このChildのnew()が呼ばれた時にParentのnew()を呼び出すには、こちらもまたoverrideを使う必要があります
package Child;
use Moose;
extends 'Parent';
override 'foo' => sub { super() };
override 'new' => sub { super() };
with 'Role';
no Moose;
というわけで皆さん気をつけてくださいね
コメント