2009-09-12 11 views
18

属性が設定されている場合はいつでも変更する必要があります。この例のように、アクセサーを自分で作成し、$selfの内容を直接書き留めていくという方法がありますか?Mooseでは、属性が設定されるたびに属性を変更するにはどうすればよいですか?

package Foo; 
use Moose; 

has 'bar' => (
    isa => 'Str', 
    reader => 'get_bar', 
); 

sub set_bar { 
    my ($self, $bar) = @_; 
    $self->{bar} = "modified: $bar"; 
} 

私はtriggerと考えましたが、同じアプローチが必要と思われました。

$selfのハッシュリファレンスで直接作業していますか?Mooseで悪い習慣とみなされていますか、それとも問題ではないかと心配していますか?

答えて

8

package Foo; 
use Moose; 

use Moose::Util::TypeConstraints; 

subtype 'ModStr' 
    => as 'Str' 
    => where { /^modified: /}; 

coerce 'ModStr' 
    => from 'Str' 
    => via { "modified: $_" }; 

has 'bar' => ( 
    isa => 'ModStr', 
    is => 'rw', 
    coerce => 1, 
); 

この方法を使用すると、すべての値が変更されるわけではありません。 ModStrとして検証に合格したものは直接使用されます。

my $f = Foo->new(); 
$f->bar('modified: bar'); # Set without modification 

この弱点はOKかもしれないまたはそれは、このアプローチが使用できなくなる可能性があります。適切な状況では、それは有利かもしれません。

6

私はハッシュリファレンスを使用すると、このようなtrigger内の罰金だと思う:バー argは、コンストラクタで渡されたとき

package Foo; 
use Moose; 

has 'bar' => ( 
    isa => 'Str', 
    is => 'rw', 
    trigger => sub { $_[0]->{bar} = "modified: $_[1]" }, 
); 

トリガーも起動します。独自のset_barメソッドまたはメソッド修飾子を定義すると、これは起こりません。

re:ハッシュリファレンス - 一般的に、上記のトリガーと同様に、属性setters/gettersに固執するのが最も簡単だと思います。

ご連絡ありがとうございます。recent post about triggersnothingmuchです。

+0

トリガーでMoose :: Manual :: Attributesをチェック - http://search.cpan.org/~drolsky/Moose-0.88/lib/Moose/Manual/Attributes.pod#Triggers –

3

ハッシュを直接処理することが懸念される場合は、別のライターを指定し、適切な名前の「パブリック」ライターからそのライターを使用することができます。

package Foo; 
use Moose; 

has 'bar' => (
    isa => 'Str', 
    reader => 'get_bar', 
    writer => '_set_bar', 
); 

sub set_bar { 
    my $self = shift; 
    my @args = @_; 
    # play with args; 
    return $self->_set_bar(@args); 
} 

この、またはトリガー、あなたは引数を操作する必要がある場合に、どのように依存する良い方法であるとして私を打ちます。

(免責事項:未テストコードは、フレーク状のエッジアクセスとネットブックにSOブラウジング、メモリから書かれた)、私はあなたが必要とする変更の種類をわからないんだけど、あなたがで必要なものを得ることができます

+0

これは素敵なクリーンですそれはコンストラクタでは機能しません。 – mikegrb

+0

@mikegrb:コンストラクタで何をしたいか分かりませんが、 'init_arg'属性修飾子を使ってコンストラクタを使って値を割り当てる場所を指定することができます。また、' BUILDARGS 'メソッド。 – Ether

9

メソッド修飾子 'around'を使用できます。このようなもの:

has 'bar' => (
    isa => 'Str', 
    reader => 'get_bar', 
    writer => 'set_bar' 
); 

around 'set_bar' => sub { 
    my ($next, $self, $bar) = @_; 
    $self->$next("Modified: $bar"); 
}; 

はい、ハッシュ値を直接操作するのは悪い方法です。

また、私が提示したオプションが必ずしも正しいものではないと考えてください。サブタイプと型変換を使用すると、ほとんどの場合適切な解決策になります。アプリケーション全体で再利用できる型のパラメータについて考えてみると、可能な任意の変更の種類がはるかに優れた設計につながります「周り」を使用して行われます。 @daotoadからの回答を参照してください。

+1

これを機能させるには、属性を定義するときにライターを宣言する必要があります。例えば、 'bar' =>(is => 'rw'、isa => 'Str'、writer => 'set_bar')を返します。 – draegtun

+0

ハッシュ値「悪い習慣」:見た(Mooseメーリングリストで)これを再確認してください。 – draegtun

+0

draegtun:Mooseが変更していない限り、デフォルトのライターは属性名です。ライターを指定したくない場合は、それを置くことができます。 –

関連する問題