odrevet has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks ! I've got some module where I need to write a lot of getters to access properties. for example, there is a module that handle the access to a warehouse items and workers (user) :
sub get_item_by_name { my ($this, $item_name) = @_; foreach my $item ( @{$this->{item}} ) { if ($item->{name} eq $item_name){ return $item; } } return undef; } sub get_user_by_id { my ($this, $user_id) = @_; foreach my $user( @{$this->{user}} ) { if ($user->{id} == $user_id){ return $user; } } return undef; }
The getters are very similar, is there some better way to have a more generic getter ? thanks

Replies are listed 'Best First'.
Re: efficient getters in module (class)
by roubi (Hermit) on Jul 25, 2009 at 15:34 UTC
    You could make your key pair (item+name, user+id) a parameter of a generic 'get' subroutine, but you would still have to figure out how to compare the values associated with the second key. You would also have to make sure that your $this object is initialized with all the possible keys (item, user) so that you can detect typos (and same for $user, $item objects). Something like this to get you started:
    sub get_by_string { my ($this, $field, $property, $value) = @_; die "Invalid field $field" if (!exists $this->{$field}); return grep { $_->{$property} eq $value } @{$this->{$field}}; } sub get_by_number { my ($this, $field, $property, $value) = @_; die "Invalid field $field" if (!exists $this->{$field}); return grep { $_->{$property} == $value } @{$this->{$field}}; }
    Your get calls would then look like this:
    my @items = $obj->get_by_string('item','name',$name); my @users = $obj->get_by_number('user','id',$id);
Re: efficient getters in module (class)
by Anonymous Monk on Jul 25, 2009 at 15:03 UTC
    The getters are very similar, is there some better way to have a more generic getter ?

    Use Moose, .... Class::Accessor...