【问题标题】:Object Attributes Getting Set Without Me Asking无需我询问即可设置对象属性
【发布时间】:2013-01-06 21:38:20
【问题描述】:

我正在使用Moose,也许它很重要,也许它不重要。

我的对象以$event 出现,我将args 属性值保存到一个变量中:

my $args = $event->args;

那个值恰好是一个散列,所以我对散列做了一些处理,特别是添加了一个新元素:

$$args{id} = 4;

这是我不明白的,当我回头查看我的$event 对象时,它里面保存了新的哈希元素!我把它设置为一个完全不同的变量,而不是对象,那为什么对象会接收它呢?

【问题讨论】:

  • 不如$args->{id} = 4
  • 我不清楚您期望分配产生什么不同。如果它不以某种方式修改对象,那么它有什么用?探索对象的内容很少是一个好主意。您应该按照文档中的说明坚持使用官方界面。

标签: perl oop object moose


【解决方案1】:

如果你想进阶一点,而不是做

has 'args' => (
  is => 'rw',
  isa => 'HashRef',
);

或者你通常做的任何事情,你都可以做类似的事情

has '_args' => (
  is => 'ro',
  isa => 'HashRef',
  default => sub { +{} },
  traits => ['Hash'],
  handles => {
    args => 'kv', # or args => 'shallow_clone'
    set_arg => 'set',
    get_arg => 'get',
    clear_arg => 'delete',
  },
);

现在,args 仍然作为 hashref 存储在对象中,但它存储在名为 _args 的私​​有属性中,您可以使用其他方法访问它,例如 my %args = $event->args(如果您使用了 kv ) 或my $args = $event->args(如果你使用shallow_clone,你会得到一个hashref,但它仍然是一个副本),$event->set_arg("foo" => "bar"); my $value = $event->get_arg("foo") 等。这是严格可选的,如果你不明白,你应该跳过它,但它帮助您构建更正交的界面并向用户隐藏实现细节。

【讨论】:

  • 这确实有道理,谢谢。我一直认为使用 hashref 设置一个新变量会克隆哈希。
【解决方案2】:

驼鹿没关系。 $event->args 返回哈希引用,因此您的副本和 $event->args 指向相同的哈希。 当您添加一个键时,它将被添加,因此它在两个引用中都可见。

为避免这种情况,您可以复制args返回的哈希:

my $args = {%{$event->args}};

复制后,您将获得对新哈希的引用,因此$args 成为对复制的引用,无需更改其他代码。

【讨论】:

    【解决方案3】:

    你从$event->args 得到的不是散列,而是散列引用。也就是说,它是一个指向散列的指针,它也被你的 args 属性所指向目的。当您说$$args{id} = 4(或等效的$args->{id} = 4)时,您正在更改$args 指向的哈希值。由于指向该哈希的指针也存储在您的对象中,因此更改也会反映在那里。

    如果你想在不影响对象的情况下更改$args中的东西,你可以复制哈希:

    my %args = %{ $event->args };
    

    【讨论】:

      猜你喜欢
      • 2018-09-16
      • 1970-01-01
      • 1970-01-01
      • 2015-03-14
      • 1970-01-01
      • 2015-12-30
      • 1970-01-01
      • 1970-01-01
      • 2022-01-20
      相关资源
      最近更新 更多