Perlで未定義メソッドを捕捉する

先日のエントリ、『ZabbixAPI.pm作ってみた』に出てくるこのようなコード、

$za->apiinfo_version();
$za->hostgroup_get({output => "extend"});

実は以下のコードと等価です。

$za->call_api("apiinfo.version");
$za->call_api("hostgroup.get", {output => "extend"});

この書き方が冗長に感じたため、未定義のメソッド呼び出しを捕捉して別のメソッドに変換する処理を追加しています。
この部分ですね。

sub AUTOLOAD{
  my $self = shift;
  my $method = our $AUTOLOAD;
  $method =~ s/.*:://;
  if($method =~ tr/_/./ == 1){
    $self->call_api($method, @_);
  }else{
    die "Wronge Method $AUTOLOAD";
  }
}

AUTOLOADメソッドを定義しておくと未定義メソッドが補足でき、メソッド名が$AUTOLOADに格納されます。

AUTOLOADの簡単な動作確認

動作確認用モジュール
package AutoloadTest;

use strict;
use warnings;

sub new {
  my $class = shift;
  my $self = bless { };
  return $self;
}

#デストタクタが上書きされないように
sub DESTROY {};

sub AUTOLOAD{
  my $self = shift;
  my @args = @_;
  my $method = our $AUTOLOAD;

  print "method : $method\n";
  print "args : ". join(',', @args) ."\n";
}

1;
テストコード
[mikeda@admin01 work]$ cat autoload_test.pl 
#!/usr/bin/perl
use strict;
use warnings;
use AutoloadTest;

my $a = AutoloadTest->new;
$a->test_func(111,222);
実行結果
[mikeda@admin01 work]$ perl autoload_test.pl 
method : AutoloadTest::test_func
args : 111,222

ちょっと魔術的ではありますが、状況によってはなかなか便利に使えます。