3

私はいくつかのPerlモジュールをMooに移行し始めましたが、セッター/ライターが1つの引数しか持てないために行き詰まりました(そうではありませんか?)。これは強制にも当てはまります。

package MyThing:
use Moo;
use Scalar::Util qw(blessed);
use SomeOtherThing;

has foo => (
  is => 'rw',
  coerce => sub {
      return $_[0] if blessed($_[0]) and $_[0]->isa('SomeOtherThing');
      return SomeOtherThing->new( @_ ); # does not work, because @_ == 1
  },       
);

簡単な使用例を次に示します。

package MyApplication;
use MyThing;

$thing = MyThing->new;
$thing->foo( 'some', 'values'); # would like to have this shortcut
$thing->foo; # expected a SomeOtherThing

# must use this ugly form instead
$thing->foo( SomeOtherThing->new('some', 'values') );

複数の引数を使用した設定をサポートするアクセサーを実装する簡単な方法はありますか?

4

2 に答える 2

4

はい、配列参照を使用します。

use Carp;
has foo => (
  is => 'rw',
  coerce => sub {
    return $_[0] if blessed($_[0]) and $_[0]->isa('SomeOtherThing');
    ref $_[0] && ref $_[0] eq 'ARRAY' or croak "foo: arg must be a SomeOtherThing or array reference";
    return SomeOtherThing->new( @{$_[0]} );
  },       
);

後で...

$thing->foo(['some', 'values']);

オブジェクトがキー/値の引数を受け入れる必要がある場合は、代わりに hashref を使用することもできます。

完全な Moose では、代わりに ArrayRef から SomeOtherThing への型変換を記述します。


免責事項

オブジェクトを作成する代わりに x/y 座標を渡すなど、場合によってはこれが役立つことがわかりますPointが、注意して使用します。

これを行うと、クラスの結合が増加します。MyThing は、SomeOtherThing のメソッドだけでなく、そのコンストラクターにも依存するようになりました。SomeOtherThing に新しいフィールドを追加する場合、MyThingfoo、MyThing のメソッドを呼び出すすべてのモジュールの両方を変更する必要がある場合があります。痛い!

于 2013-03-15T15:33:30.680 に答える
1

現在のバージョンの Moo ではセッターで複数の引数にアクセスできないため、この機能を拡張するために Perl モジュールを作成しました。現在は実験的なので、お気軽にClass::Accessor::Coerce at PrePANにコメントしてください。

于 2013-03-20T11:56:14.953 に答える