Reputation: 329
I'm currently refactoring some code and am trying to remove the use of symbolic references below for dispatching a function based off input.
package Parent;
use strict;
use warnings;
sub dispatch{
my ($self, $funcname) = @_;
no strict "refs";
if($self->can($funcname)){
$self->$funcname();
}
else{
$self->default_func();
}
use strict;
}
sub a{
...
}
sub b{
...
}
#...lots more functions...
sub default_func{
..
}
package Child;
use strict;
use warnings;
use Parent;
our @ISA = qw(Parent)
sub c{
..
}
I considered using a dispatch table like below, but this seems less than ideal since there's quite a bit of extra maintenance involved with tracking down all the subclasses and copying all the functions involved.
package Parent;
use strict;
use warnings;
{
my $funcs ||= {
a => sub { shift->a },
b => sub { shift->b },
c => sub { shift->c },
#...lots of functions...
DEFAULT => sub {shift->default_func}
}
sub dispatch{
my ($self, $funcname) = @_;
my $func = $funcs->{$funcname} || $funcs->{DEFAULT};
$self->$func();
}
}
Additionally, I considered turning the dispatch table to into a member so that the parent class doesn't have to be aware of the child classes as well. Then each child class would add its own functions to the dispatch table. Originally I did not want the dispatch table to be a member since I only wanted it to be exposed to one function but perhaps it's unavoidable. But in the end, turning it into a member does not fix the problem of the extra boilerplate and maintenance involved.
Is there a better way? This seems like a lot more work than symbolic references. I'm willing to do the extra work if it allows me to avoid a hacky solution but I'm not sure which direction to go from here.
Upvotes: 3
Views: 157
Reputation: 56
Why wouldn't you use AUTOLOAD?
package Parent;
use vars qw( $AUTOLOAD );
sub AUTOLOAD {
return if $AUTOLOAD =~ m/^.*::(DESTROY)$/;
my ($self, @params) =@_;
return $self->$AUTOLOAD() if($self->can($AUTOLOAD)){
return $self->default_func();
}
Upvotes: 0
Reputation: 8532
Your original code example works fine under use strict
. The $obj->$method(...)
form does not require symbolic references. It's a widely-used technique and is considered good practice.
Also, note that even if you had to no strict
, there is no need to use strict
again at the end of the function as in your example. strict
is a lexical pragma, so its effects are limited to its containing scope anyway.
Upvotes: 3