我开始将几个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') );
是否有一种简单的方法来实现支持使用多个参数进行设置的访问器?
答案 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。