Moose数组属性:我如何使用set方法?

时间:2012-12-15 22:02:53

标签: arrays perl moose traits

我想将一个数组定义为一个类的属性,并在实例化该类时用一些数据填充它。

我认为可以使用$self->attribute->set($id, $value)方法来设置给定索引上的元素。至少这是我从穆斯documentation中所理解的。

但是当我尝试

use Data::Dumper qw( Dumper );
use Moose;

has cells => (
    is => 'rw',
    traits  => ['Array'],
    isa     => 'ArrayRef',
    default => sub { [] },
);

my $app = __PACKAGE__->new();
$app->cells->set($_, $_) for 0..3;
print(Dumper($app->cells));

我得到了

Can't call method "set" on unblessed reference

如何让set工作?

3 个答案:

答案 0 :(得分:6)

use Data::Dumper qw( Dumper );
use Moose;

has cells => (
    is => 'rw',
    traits  => ['Array'],
    isa     => 'ArrayRef',
    default => sub { [] },
    handles => {                   # <---
       set_cell => 'set',          # <---
    },                             # <---
);

my $app = __PACKAGE__->new();
$app->set_cell($_, $_) for 0..3;   # <---
print(Dumper($app->cells));

尽管在评论中声称相反,但它在BUILD中也可以正常工作。

use Data::Dumper qw( Dumper );
use Moose;

has cells => (
    is => 'rw',
    traits  => ['Array'],
    isa     => 'ArrayRef',
    default => sub { [] },
    handles => {
       set_cell => 'set',
    },
);

sub BUILD {
    my ($self) = @_;
    $self->set_cell($_, $_) for 0..3;
}

my $app = __PACKAGE__->new();
print(Dumper($app->cells));

答案 1 :(得分:3)

@ ikegami的回答是正确的。这是一个扩展的解释。

问题在于这一行:

$app->cells->set($_, $_) for 0..3;

为了更清楚,让我们摆脱循环并展开它。

my $cells = $app->cells;
$cells->set(0, 0);

$app->cells返回一个普通数组引用,就像您在has cells调用中定义的一样。所以$ cells只不过是一个简单的,无法使用的数组引用。你不能在那上面调用任何方法,这是(不幸的)Perl如何工作,除非你进入autobox

the documentation中注意,所有提供的方法都是在对象上调用的,而不是在属性返回的东西上调用的。此外,文档在这一点上并不清楚,每个方法都附加了属性的名称。您没有致电count致电count_cells。您不能致电set致电set_cells

$app->set_cells(0, 0);
print $app->count_cells;

答案 2 :(得分:3)

你不这样做。 set上没有$app->cells方法,因为$app->cells是数组引用,而不是对象,因此没有方法。将Array本机特征应用于属性不会使arrayref成为对象;它只是通过使用特征提供的方法使该属性能够回答handles个请求。

如果你想能够在一个未经验证的数组引用上调用方法,你可以考虑使用Moose::Autobox,但如果考虑到得墨忒耳法则你会发现原生特征可以让你构建一个比让用户直接捅你的数据成员更强大的界面。