【问题标题】:Moose array attributes: how do I use a set method?Moose 数组属性:如何使用 set 方法?
【发布时间】:2012-12-15 22:02:52
【问题描述】:

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

我认为可以使用$self->attribute->set($id, $value) 方法在给定索引上设置元素。至少这是我从 Moose 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 工作?

【问题讨论】:

  • 我想问一下我改post的属性怎么用set()方法,希望现在清楚了。
  • set 不是直接可调用的方法。这看起来像是handles 的一种方法。你不能自己称呼它。

标签: arrays perl moose traits


【解决方案1】:
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));

尽管在 cmets 中有相反的说法,但它在 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));

【讨论】:

  • 不,很抱歉,这并不能解决我的问题。我编写了一个演示脚本,其唯一目的是演示我是如何做到的以及出了什么问题。不幸的是,该脚本不再存在,因为我的原始帖子已被更改...在 BUILD 方法中设置单元格时,应用此答案的建议仍然会产生错误。
  • @capfan ikegami 的回答对我有用。如果您正在做更多涉及 BUILD 的事情,请编辑您的帖子以向我们展示。
  • @capfan,如果您应用我展示的两个更改(handlesset_cell),并且如果您停止通过执行$self-&gt;cells(\@cells); 来破坏您设置的单元格,它可以与您的原始代码一起正常工作。
  • 啊哈,现在我明白了。感谢所有 cmets 和解释。如前所述,给出了包含 BUILD 方法的脚本的完整(但最小)代码示例,但已对其进行了编辑。现在,给出答案的人必须处理它。 Schwern 的回答最有帮助。那么,谁获得了荣誉?
  • 代码远非最小。如您所见,BUILD 没有什么特别之处。在你问这个问题之前,一个巨大的分心应该已经消除了。你没有,而且你一直在提起它,因为你没有。
【解决方案2】:

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

问题在于这一行:

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

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

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

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

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

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

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

    • 很好的解释。我想不出一个好的表达方式。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-14
    • 1970-01-01
    • 1970-01-01
    • 2013-09-02
    • 2016-06-17
    • 2013-05-20
    相关资源
    最近更新 更多