3

現在、いくつかのコードをリファクタリングしており、入力に基づいて関数をディスパッチするための以下のシンボリック参照の使用を削除しようとしています。

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

さらに、親クラスが子クラスを意識する必要がないように、ディスパッチ テーブルをメンバーに変換することも検討しました。次に、各子クラスは独自の関数をディスパッチ テーブルに追加します。元々、ディスパッチ テーブルを 1 つの関数に公開するだけでよかったので、ディスパッチ テーブルをメンバーにしたくありませんでしたが、おそらくそれは避けられません。しかし、結局のところ、それをメンバーに変えても、余分なボイラープレートと関連するメンテナンスの問題は解決されません。

より良い方法はありますか?これは、シンボリック参照よりもはるかに多くの作業のようです。ハッキーな解決策を回避できる場合は、追加の作業を喜んで行いますが、ここからどの方向に進むべきかわかりません。

4

2 に答える 2

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();
}
于 2013-10-17T12:57:49.503 に答える