Предположим, у меня несколько ролей, каждая из которых определяет набор предметов:
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 "не совсем стабилен", а также что "текущая реализация является чем-то вродевзломать, и должен быть заменен более надежным ".Поэтому я исследую, можно ли это сделать, не полагаясь на такой «взлом».
Предупреждение: если вы читаете это в будущем, перейдите, чтобы проверить POD для MooseX :: ComposedBehavior (текущая версия: 0.003), поскольку он мог измениться за это время.Вещи меняются быстро.Авторы 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;
...
}
Обновление: Поскольку разные люди просили меня на 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;
...
}