3

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

我认为可以使用一种$self->attribute->set($id, $value)方法在给定索引上设置元素。至少这是我从 Moose文档中了解到的。

但是当我尝试

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

4

3 回答 3

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));
于 2012-12-15T22:34:50.973 回答
3

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

问题在于这一行:

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

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

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

$app->cells返回一个普通数组 ref,就像您在has cells调用中定义的那样。所以 $cells 只不过是一个普通的、未受祝福的数组引用。你不能调用任何方法,这就是(不幸的是)Perl 的工作原理,除非你进入autobox

请注意,在文档中提供的所有方法都是在对象上调用的,而不是在属性返回的事物上。此外,文档在这一点上并不清楚,每个方法都附加了属性的名称。你不叫count你打电话count_cells。你不叫set你打电话set_cells

$app->set_cells(0, 0);
print $app->count_cells;
于 2012-12-15T23:31:29.003 回答
3

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

如果您希望能够在 unblessed 数组引用上调用方法,您可能会考虑使用Moose::Autobox,但如果您考虑得墨忒耳法则,您会发现原生特征可以让您构建一个比它更健壮的接口让用户直接戳你的数据成员就可以了。

于 2012-12-16T00:08:59.730 回答