对象属性在没有我的情况下设置

时间:2013-01-06 21:38:21

标签: perl oop object moose

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

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

my $args = $event->args;

这个值碰巧是哈希值,所以我对哈希做了一些事情,特别是添加了一个新元素:

$$args{id} = 4;

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

3 个答案:

答案 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