2011-01-31 6 views
4

それぞれがアイテムのセットを定義し、私は複数の役割を持っていると仮定します。Perlクラスの属性の構成ですか?

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が「あまり安定していない」こと、そして「現在の実装はハックのものであり、より堅牢なものに置き換えなければならない」と(記事の執筆時点では)言う。したがって、私は、このような "ハック"に頼ることなくこれを達成できるかどうかを調べています。それはその間に変更されている可能性があるため

警告:あなたは、将来的にこれを読んでいる場合MooseX::ComposedBehaviorのPOD(0.003現在のバージョン)を確認するために行ってください。物事はすぐに変わる。 CPANの著者は新しいバージョンをリリースします。現時点で「あまり安定していない」ものは、​​将来的にはより安定していくかもしれません。他のモジュールがあるかもしれません。自分自身で調べて。

my @items = map $_->items, @ISA; ただし、これはムーゼでは機能しません。より良い、より信頼性の高いソリューションはありますか?


更新:さまざまな人々は、私は私の以前のアサーションMooseXを削除#moose IRC channelで私を要求したよう

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; 

    ... 
} 

更新:私はこの3行のソリューションになってしまいました:: 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; 
    ... 
} 
+3

私はあなたがここで役割をしたいとは思わない。 "B"と "C"の役割をFooに組み込むと、 "items"メソッドとの競合が発生し、Fooはコンパイルされないだけでなく、コンパイルする方法も独自の "items " 方法。 –

答えて

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 {} 

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

+0

私は 'override items => sub {return super()、qw(banana)};'を使うことを考えました。私の役割はアプリケーションの機能を記述し、それぞれがアプリケーションの設定に適用される 'Data :: Schema'検証スキーマを定義します。 – Alessandro

+0

'around'を使った別のアプローチでは、代わりにBUILDARGSをラップして、最初の入力を一度変更することができます(ロールがBUILDARGSに影響を与えるかどうかを思い出しました)。 – Carl

+1

@Allesandro - あなたはクラスと混乱しているロールであり、ロールのオーバーライド/スーパーは、自分自身ではなく、作成されたクラスのコンテキストで実行されます。 –

5

IRCで前にMooseX::ComposedBehaviorを指摘した後、なぜあなたはそれを使用すべきではないと思っているのですか?結局のところ、それはあなたが持っている問題を正確に解決します。

はい、今後インターフェイスが少し変更される可能性があります。しかし、あなたはそれらのわずかな変化に適応するためにどれだけの仕事をするでしょうか?これと比較して、代替ソリューションを思いついて実際に実装するのにどれくらいの時間がかかると思いますか?正確さと堅牢性の点で、あなたのソリューションはMooseX::ComposedBehaviorとどのように比肩していると思いますか?少なくとも私はRJBSが最初に発明したホイールを再発明し、私の解決策がより良くなると期待しています。

また、今後の変更について警告するモジュールについて本当に心配している場合は、その著者と一緒に作業して、彼が安定していると宣言してくれるような形にしてください。あなたの特定の用途のためのテストをもう少し書いてください。リカルドと話すと、彼は素敵な男です。

+2

私は、MooseX :: ComposedBehaviorの警告で、PODの "現在の実装はハックのようなもの"で、APIは "あまり安定しておらず、まだ変更されるかもしれない"という警告を少し怖がっていたので、 「ハック」に反復することなく満足することができます。それ以外は、私はリカルドのモジュールをよく知っていて、私はその質について議論していません:-) – Alessandro

+0

@Alessandro:宇宙のAPIはかなり安定していないかもしれないし、まだ変更するかもしれないので、 ) – Ether

+2

また、ドキュメントのAPIから逸脱した場合には、変更が大変であり、問​​題が発生する可能性があるとも言われています。どちらがあなたのユースケースに影響を与えるかわかりません。 – hdp

関連する問題