20

設定するたびに変更する必要がある属性がある場合、この例で行われているように、アクセサーを自分で記述し、のコンテンツを直接いじる以外に、これを行う巧妙な方法はあり$selfますか?

package Foo;
use Moose;

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

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

を検討triggerしましたが、同様のアプローチが必要なようでした。

Moose$selfで考えられる悪い習慣でハッシュ参照を直接操作していますか、それとも問題がないことを心配していますか?

4

4 に答える 4

10

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

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

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

はい、ハッシュ値を直接操作することは悪い習慣と見なされます。

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

于 2009-09-13T00:58:35.687 に答える
8

ハッシュ参照を使用することは、次のようなトリガー内で問題ないと思います。

package Foo;
use Moose;

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

トリガーは、barargがコンストラクターで渡されたときにも起動します。独自のset_barメソッドを定義する場合、またはメソッド修飾子を使用する場合、これは発生しません。

re:ハッシュリファレンス-(上記のトリガーのように)簡単な代替手段がない場合を除いて、一般的に属性セッター/ゲッターを使用するのが最善だと思います。

ところで、トリガーに関するこの最近の投稿はそれほど興味深いものではありません。

于 2009-09-12T19:15:53.473 に答える
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

この弱点は問題ないかもしれませんし、このアプローチが使えなくなるかもしれません。適切な状況では、それは利点になることさえあります。

于 2009-09-12T23:48:49.023 に答える
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を閲覧する)

于 2009-09-12T23:38:03.633 に答える