4

複数のロールがあり、それぞれが一連のアイテムを定義しているとします。

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?
    ....
}

考えられる解決策の 1 つはMooseX::ComposedBehaviorを採用することですが、その POD は (もちろん、執筆時点では) その API は「完全に安定していない」と述べており、「現在の実装はハックのようなものであり、置き換える必要がある」とも述べています。より堅牢なものによって」。そのため、このような「ハック」に頼らずにこれを達成できるかどうかを調査しています。

警告:今後これを読む場合は、MooseX::ComposedBehavior (現在のバージョン: 0.003) の POD を確認してください。その間に変更されている可能性があります。物事は急速に変化します。CPAN の作成者は新しいバージョンをリリースします。現時点で「安定していない」ものは、​​将来的にはより安定する可能性があります。他のモジュールがあるかもしれません。自分自身で調べて。

理想的には、次のようなものがあるはずです:my @items = map $_->items, @ISA; ただし、Moose では機能しません。より優れた信頼性の高いソリューションはありますか?


更新:私はこの3行の解決策になりました:

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;
    ...
}
4

2 に答える 2

7

使用する必要がありますaround

package A;
use Moose::Role;
requires 'items';
around items => sub {
    my ($orig, $self, @args) = @_;
    return ($self->$orig(@args), qw/apple orange/);
};

package B;
use Moose::Role;
requires 'items';
with 'A'; # not required, do it if you want it
around items => sub {
    my ($orig, $self, @args) = @_;
    return ($self->$orig(@args), qw/watermelon/);
};

package C;
use Moose::Role;
requires 'items';
around items => sub {
    my ($orig, $self, @args) = @_;
    return ($self->$orig(@args), qw/banana/);
};

package Class;
use Moose;
with qw/B C/;
sub items {}

しかし、一般に、データを表現するためにクラスを使用することは間違っています。それがクラスの インスタンスの目的です。あなたの例は非常に些細なことなので、これ以上のアドバイスを提供することは困難です。あなたは本当に何をしようとしていますか?

于 2011-01-31T11:58:29.250 に答える
5

以前に IRC について指摘してもらった後MooseX::ComposedBehavior、なぜ IRC を使用すべきではないと感じているのか完全にはわかりません。結局のところ、あなたが抱えている問題を正確に解決します。

はい、インターフェースは将来的にわずかに変更される可能性があると言っています。しかし、それらのわずかな変化に適応するのにどれだけの労力がかかりますか? それに比べて、代替ソリューションを考え出し、実際にそれを実装するには、どれくらいの時間がかかると思いますか? あなたのソリューションは、MooseX::ComposedBehavior正確性や堅牢性などの点でどのように比較されると思いますか? 少なくとも、RJBS によって最初に発明されたホイールを再発明し、自分のソリューションがより良いものになると期待することに自信を持ちません。

また、モジュールが将来の変更の可能性について警告することを本当に心配している場合は、その作成者と協力して、安定していると宣言するために彼が満足する形にするのを手伝ってください。特定のユースケース用にさらにいくつかのテストを作成します。リカルドと話してください、彼はナイスガイです。

于 2011-01-31T13:59:35.760 に答える