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.