调度方法没有符号引用

时间:2013-10-09 17:45:25

标签: perl oop

我目前正在重构一些代码,并尝试删除下面使用的符号引用来根据输入调度函数。

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解决方案,但我不知道从这里走哪个方向。

2 个答案:

答案 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();
}