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