如何将多个参数传递给Perl Moo中的setter / writter

时间:2013-03-15 14:04:00

标签: perl moose moo

我开始将几个Perl模块迁移到Moo但是因为setter / writer只能有一个参数(不能吗?)而被卡住了。这也适用于胁迫:

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') );

是否有一种简单的方法来实现支持使用多个参数进行设置的访问器?

2 个答案:

答案 0 :(得分: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添加新字段,则可能需要同时更改MyThing 所有调用MyThing的foo方法的模块。哎哟!

答案 1 :(得分:1)

使用当前版本的Moo无法访问setter中的多个参数,因此我编写了一个Perl模块来扩展此功能。它目前是实验性的,因此请随意评论Class::Accessor::Coerce at PrePAN