我正在使用Moose
,也许这很重要,也许不是。
我的对象以$event
形式出现,我将args
属性值保存到变量中:
my $args = $event->args;
这个值碰巧是哈希值,所以我对哈希做了一些事情,特别是添加了一个新元素:
$$args{id} = 4;
这是我不明白的,当我回去查看我的$event
对象时,它已经保存了新的哈希元素!我将它设置为一个完全不同的变量,而不是对象,那么为什么对象会接收它呢?
答案 0 :(得分:2)
驼鹿并不重要。 $event->args
返回哈希反射,因此您的副本和$event->args
指向相同的哈希值。
当您添加一个键时,它将被添加,因此从两个引用中都可以看到它。
为避免这种情况,您可以复制args
返回的哈希:
my $args = {%{$event->args}};
复制后,您将获得对新哈希的引用,因此$args
将成为复制的引用,无需更改其他代码。
答案 1 :(得分: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")
等。这是严格可选的,您应该如果您不理解它,请跳过它,但它可以帮助您构建更正交的界面并隐藏用户的实现细节。
答案 2 :(得分:1)
从$event->args
返回的内容不是哈希值,而是哈希引用。也就是说,它是指向哈希的指针,该哈希也由{{1}指向你对象中的属性。当您说args
(或等效的$$args{id} = 4
)时,您正在更改$args->{id} = 4
指向的哈希值。由于指向该哈希的指针也存储在您的对象中,因此更改也会反映在那里。
如果你想更改$args
中的内容而不影响对象,你可以复制哈希:
$args