假设我有多个角色,每个角色定义一组项目:
package A;
use Moose::Role;
sub items () { qw/apple orange/ }
package B;
use Moose::Role;
with 'A';
sub items () { qw/watermelon/ }
package C;
use Moose::Role;
sub items () { qw/banana/ }
假设我在另一个类中使用它们并且我想收集所有这些项目:
package Foo;
use Moose;
with qw(B C);
sub do_something {
my $self = shift;
my @items = ???; # How can I get apple, orange, watermelon, banana here?
....
}
一种可能的解决方案是采用MooseX::ComposedBehavior,但它的 POD 说(当然在撰写本文时)它的 API“不太稳定”并且“当前的实现有点像 hack,应该被替换由一个更强大的“。因此,我正在调查这是否可以在不依赖这种“黑客”的情况下完成。
警告:如果您将来阅读此内容,请检查MooseX::ComposedBehavior(当前版本:0.003)的 POD,因为它可能同时发生了变化。事情变化很快。CPAN 作者发布新版本。目前“不太稳定”的东西将来可能会变得更加稳定。甚至可能还有其他模块。自行检查。
理想情况下应该有类似的东西:my @items = map $_->items, @ISA;
但是这不适用于 Moose。有没有更好更可靠的解决方案?
更新:我最终得到了这个三行解决方案:
package A;
use Moose::Role;
sub items () { qw/apple orange/ }
package B;
use Moose::Role;
with 'A';
sub items () { qw/watermelon/ }
package C;
use Moose::Role;
sub items () { qw/banana/ }
package Foo;
use Moose;
with qw(B C);
sub items () {}
sub do_something {
my $self = shift;
my @items = map $_->execute, grep $_,
map $_->get_method('items'),
$self->meta->calculate_all_roles_with_inheritance;
...
}
更新:由于许多人在#moose IRC 频道中向我提出要求,我删除了我之前关于 MooseX::ComposedBehavior “不稳定”的断言,并将其替换为从其 POD 中获取的文字文本。
更新:我写了一个MooseX::Collect模块,它允许以下语法:
package Foo;
use Moose;
use MooseX::Collect;
collect 'items';
with qw(B C);
sub do_something {
my $self = shift;
my @items = $self->items;
...
}