我开始意识到这适合初学者:
package Bad; has 'arr' => ( is => 'rw','ArrayRef[Str]' ); package main; my $bad = Bad->new(arr => [ "foo","bar" ]); print $bad->arr->[0],"\n";
输入特征.不过,我对特质API感到不知所措.我误解了什么吗?我能以某种方式获得此API吗? :
print $bad->arr->get(0),"\n";
细节
查看Moose::Meta::Attribute::Native::Trait::Array 中的规范特征示例
package Stuff; use Moose; has 'options' => ( traits => ['Array'],is => 'ro',isa => 'ArrayRef[Str]',default => sub { [] },handles => { all_options => 'elements',add_option => 'push',map_options => 'map',filter_options => 'grep',find_option => 'first',get_option => 'get',join_options => 'join',count_options => 'count',has_options => 'count',has_no_options => 'is_empty',sorted_options => 'sort',},); no Moose; 1;
使用如此声明的对象,例如:
my $option = $stuff->get_option(1);
我真的不喜欢我获得的一个数组属性,并且必须在我的Stuff类中手动命名11个方法 – 一个用于每个操作,可以对’选项’执行操作.不一致的命名必然会发生,而且很臃肿.
我如何(优雅地)获得如下API:
my $option = $stuff->options->get(1);
Moose::Meta::Attribute::Native::Trait::Array 中的所有方法都是以类型安全的方式实现的吗?
然后,每个数组上的所有操作都以完全相同的方式命名…
(我实际上使用鼠标,但大多数鼠标与Moose相同)
解决方法
我认为将API转换为该格式的最佳方法是为选项创建一个新对象,并将方法直接委托给它.就像是:
package Stuff; use Moose; use Stuff::Options; has 'options' => ( 'is' => "ro",'isa' => "Stuff::Options",'default' => sub { Stuff::Options->new },); no Moose; 1;
然后在Stuff / Options.pm中:
package Stuff::Options; use Moose; has '_options' => ( 'is' => "ro",'isa' => "ArrayRef[Str]",'traits' => [ "Array" ],'default' => sub { [] },'handles' => [ qw(elements push map grep first get join count is_empty sort) ],); no Moose; 1;
这将允许您的示例中的代码工作($stuff-> options-> get(1)).