Search code examples
perloopobjectmoose

Object Attributes Getting Set Without Me Asking


I'm using Moose, maybe it matters, maybe it doesn't.

My object comes in as $event, and I save the args attribute value to a variable:

my $args = $event->args;

That value happens to be a hash, so I do some stuff to the hash, specifically adding a new element:

$$args{id} = 4;

Here's what I don't understand, when I go back to look at my $event object, it has that new hash element saved inside! I set it to a completely different variable, not the object, so why does the object receive it?


Solution

  • If you want to get a little bit advanced, instead of doing

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

    or whatever you normally do, you can do something like

    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',
      },
    );
    

    now, the args are still stored in the object as a hashref, but it's stored in a private attribute named _args, and you use other methods to access it, for example my %args = $event->args (if you used kv) or my $args = $event->args (if you used shallow_clone, you get a hashref, but it's still a copy), $event->set_arg("foo" => "bar"); my $value = $event->get_arg("foo") etc. This is strictly optional, and you should skip it if you don't understand it, but it helps you build a more orthogonal interface and hide implementation details from your users.