クラス内でメソッドを動的に定義したいと思います。以下のスケルトンよりもやや複雑なトレーサーを作成しています。これも状態を認識していますが、それは私の問題とは関係ありません。sprintf を呼び出し、改行をテキスト \n に置き換える trace メソッドを使用して TraceSlave クラスを作成しました。
基本的に、トレースを次のようにインスタンス化したいと思います。
my @classes = qw(debug token line src match);
my $trace = Tracer->new(\@classes);
そして、動的に定義されたトレースのメソッドを次のように呼び出すことができるはずです。
$trace->debug("hello, world");
$trace->match("matched (%s)(%s)(%s)(%s)(%s)", $1, $2, $3, $4, $5);
したがって、私の Tracer クラスは次のようになります。
package Tracer;
  sub new {
    my $class = shift;
    my $self = {};
    my @traceClasses = @{$_[0]};
    bless $self, $class;
    for (@traceClasses) {
# This next line is wrong, and the core of my question
      $self->$_ = new TraceSlave($_, ...)->trace
    } # for (@traceClasses)
  }
それはコンパイルされないからです。基本的には、TraceSlave のインスタンスの trace メソッドとして、Tracer インスタンスのメソッドを定義したいと考えています。ループで。
AUTOLOAD または eval で実行できますが、それは間違っています。正しい方法は何ですか?
完全を期すために、TraceSlave を次に示します。大丈夫だよ
package TraceSlave;
  sub new {
    my $self = { header => $_[1], states => $_[2], stateRef => $_[3] };
    bless $self, $_[0];
    return $self;
  } # new()
  sub trace {
    my $self = shift;
    my @states = @{$self->{states}};
    if ($states[${$self->{stateRef}}]) { # if trace enabled for this class and state
      my @args;
      for (1..$#_) { ($args[$_-1] = $_[$_]) =~ s/\n/\\n/g; } # Build args for sprintf, and replace \n in args
      print $self->{header}.sprintf($_[0], @args)."\n";
    }
  } # trace()