Perl Moose对象可以直接使用数组/哈希属性吗?

时间:2013-11-19 18:55:05

标签: arrays perl attributes moose

在Perl中可以这样做吗?

package Person;
use Moose;

has 'friends' => ( is => 'rw', isa => 'Array', default => () );

我看到perl编译器不接受这种特殊的语法,但是我使用了错误的语法,还是根本不可能?我是否必须使用数组引用?

我对perl很新,所以问题可能是愚蠢的,我觉得答案是“不”,但我没有发现任何提及。

提前致谢

3 个答案:

答案 0 :(得分:7)

“列表”有很多定义。假设你是一个Person对象的集合或有序集合,我会使用一个我使用引用传递给访问者的数组

has friends => (
   is      => 'rw',
   isa     => 'ArrayRef[Person]',
   default => sub { [] },
);

push @{ $o->friends }, $person;

for (@{ $o->friends }) {
   ...
}

您可以使用Moose::Meta::Attribute::Native::Trait::Array添加有用的方法。

has friends => (
   traits  => [qw( Array )],
   is      => 'rw',
   isa     => 'ArrayRef[Person]',
   default => sub { [] },
   handles => {
      push_friends => 'push',
   },
);

$o->push_friends($person);

for (@{ $o->friends }) {
   ...
}

答案 1 :(得分:4)

这不是你要求的,而是看数组特征 - http://search.cpan.org/dist/Moose/lib/Moose/Meta/Attribute/Native/Trait/Array.pm。由于所有实例的值都存储在hashref中,因此您无法存储标量值以外的任何值,这意味着您需要使用引用。这将处理使用内部arrayref所需的所有样板文件。

package Person;
use Moose;

has 'friends' => ( is => 'ro', 
                   traits  => ['Array'],
                   isa => 'ArrayRef[Str]',
                   default => sub { [] },
                   handles => {
                                 all_friends    => 'elements',
                                 add_friend     => 'push',
                                 map_friends    => 'map',
                                 filter_friends => 'grep',
                                 find_friend    => 'first',
                                 get_friend     => 'get',
                                 join_friends   => 'join',
                                 count_friends  => 'count',
                                 has_friends    => 'count',
                                 has_no_friends => 'is_empty',
                                 sorted_friends => 'sort',
                             },

                 );

答案 2 :(得分:0)

作为一个至少使获取/设置更容易的简单答案,您可以编写自己的访问器函数以将数组ref包装到数组中。例如:

package Person;
use Moo;

has 'friendsRef' => ( is => 'rw', default => sub { []; } );

## A 'set/get' wrapper for friendsRef
sub Person::friends {
  my ($self, @list) = @_;
  return @{$self->friendsRef} unless $#list>=0;
  return $self->friendsRef(\@list);
}

## Example bonus function for adding to list
sub Person::addFriends {
  my ($self, @list) = @_;
  return push(@{$self->friendsRef}, @list);
}

示例代码用法可能是:

my $p = Person->new();

$p->friends('Dave','Jerry');
print "Friends are: ",join(', ',$p->friends()),"\n";

$p->friends('Bob','Dave');
print "Friends are: ",join(', ',$p->friends()),"\n";

$p->addFriends('Joe','Cletus');
print "Friends are: ",join(', ',$p->friends()),"\n";

## Note that "$p->friends()" is not a scalar, it's a sub returning an array,
## so instead of "$#{$p->friends()}" you'd want "scalar($p->friends())"
print "Number of friends is ",scalar($p->friends()),"\n";

输出为:

Friends are: Dave, Jerry          
Friends are: Bob, Dave            
Friends are: Bob, Dave, Joe, Cletus                                 
Number of friends is 4