1

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

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

my $args = $event->args;

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

$$args{id} = 4;

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

4

3 回答 3

2

如果你想获得一点进步,而不是做

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")等。这完全是可选的,如果您不理解它应该跳过它,但它可以帮助您构建一个更加正交的接口并隐藏用户的实现细节。

于 2013-01-07T00:04:10.910 回答
2

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

为避免这种情况,您可以复制由以下内容返回的哈希args

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

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

于 2013-01-06T21:45:27.583 回答
1

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

如果您想在$args不影响对象的情况下更改内容,可以制作哈希的副本:

my %args = %{ $event->args };
于 2013-01-06T21:45:20.997 回答