How should I define a Moose object subroutine after its initialization?
I'm writing an object module using Moose and I plan to serialize (nstore
) the created objects.
Examine the following (simplified!) example:
package MyObj 0.001;
use Moose;
use namespace::autoclean;
has 'size' => (
is => 'ro',
isa => 'Int',
required => 1,
);
sub some_sub {
my ($self, @more) = @_;
if ($self->size() < 100) # do something;
elsif (($self->size() < 500)) # do something else;
elsif (($self->size() < 7500)) # do something else;
# ...
}
1;
some_sub
acts differently depending on size
. Since size
is read-only, it remains constant after the object has been initialized.
So, assuming I call some_sub
zillion times, it's a pity that I have to go through all the if
s each time.
I'd better do this once after the object has been initialized, then set some_sub
to be a simpler function with noif
s at all.
But... how can I do that?
UPDATE
Perhaps I should add a lazy
attribute of type subref that will hold a reference to the chosen subroutine. some_sub
will then simply call $self->chosen_sub->(@_)
. What do you think?
has calculation_method => (is => 'ro', lazy_build => 1, init_arg => undef);
sub _build_calculation_method {
my $self = shift;
return '_calculate_small' if $self->size < 100;
return '_calculate_medium' if $self->size < 500;
return '_calculate_large' if $self->size < 7500;
return '_calculate_enormous';
}
sub _calculate_small { ... }
sub _calculate_medium { ... }
# etc.
sub calculate {
my $self = shift;
my $method = $self->calculation_method;
return $self->$method(@_);
}
As a bonus, calculation_method
is now serializable too.