我目前正在重构一些代码,并尝试删除下面使用的符号引用来根据输入调度函数。
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{
..
}
我考虑使用如下的调度表,但这似乎不太理想,因为跟踪所有子类并复制所有相关函数需要进行相当多的额外维护。
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();
}
}
此外,我考虑将调度表转换为成员,以便父类也不必知道子类。然后每个子类将其自己的函数添加到调度表。最初我不希望调度表成为成员,因为我只想让它暴露给一个函数,但也许它是不可避免的。但最终,将其变成一个成员并不能解决所涉及的额外样板和维护问题。
有更好的方法吗?这似乎比符号引用要多得多。我愿意做额外的工作,如果它允许我避免一个hacky解决方案,但我不知道从这里走哪个方向。
答案 0 :(得分:3)
您的原始代码示例在use strict
下正常工作。 $obj->$method(...)
表单不需要符号引用。这是一种广泛使用的技术,被认为是一种很好的做法。
另请注意,即使您必须no strict
,也不需要在函数末尾再次use strict
,如您的示例所示。 strict
是一个词汇编纂,所以它的影响仅限于它的包含范围。
答案 1 :(得分:0)
为什么不使用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();
}