アクセッサの自動生成(AUTOLOAD編)
以前アクセッサを自動生成する方法を紹介していたのですが、今回はAUTOLOADを使用した場合を紹介します。
http://d.hatena.ne.jp/okamuuu/20100417/1271479559
AUTOLOADとは
ある名前空間に存在するメソッドを実行するように指示したのに、そのメソッドが定義されていない
場合にこのAUTOLOADを用意しておくと、代わりに実行します。
1. スクリプト
use strict; use warnings; eval { package Hoge; sub new { bless $_[1], $_[0] } sub AUTOLOAD { no strict 'vars'; print $AUTOLOAD, 'がAUTOLOADメソッドを呼び出した!!', "\n" } sub DESTROY { print 'DESTROYメソッドが実行された!!', "\n" } 1; }; my $hoge = Hoge->new( { name => 'okamura', lang => 'jp' } ); $hoge->name; # nameメソッドが定義されていないので代わりにAUTOLOADが呼ばれる $hoge->lang; # langメソッドが定義されていないので代わりにAUTOLOADが呼ばれる exit; # $hogeの寿命がつきるので DESTROYが呼ばれる
2. 実行
:!perl % Hoge::nameがAUTOLOADメソッドを呼び出した!! Hoge::langがAUTOLOADメソッドを呼び出した!! DESTROYメソッドが実行された!!
$AUTOLOADには本来実行したかったメソッド名を完全修飾名でとりだせます。
DESTROYメソッドが定義されていないのに、AUTOLOADメソッドを定義すると、デストラクションと同時にAUTOLOADメソッドを呼び出すのでこのようにDESTROYを定義しています。
AUTOLOADが読み込まれたタイミングでシンボルテーブルを作成
まだ定義されていないメソッドを実行した場合シンボルテーブルからそのメソッドを発見できないのでAUTOLOADを探します。
なので最初にAUTOLOADが呼ばれたタイミングでシンボルテーブルからそのメソッドを発見できる状態にして、2回目以降はAUTOLOADを呼ばずにシンボルテーブルを参照できるようにする、というサブルーチンが必要となるまで定義されない、というトリックを今回紹介します*1。
1. スクリプト
#!/usr/bin/perl #use strict; #use warnings; eval { package Hoge; sub new { bless $_[1], $_[0] } sub AUTOLOAD { # print 'this is ', $AUTOLOAD; if ( $AUTOLOAD =~ m/.*::(.*)/ ) { if ( $1 eq 'DESTROY' ) { return 1 } print '(初めて呼ばれたのでシンボルテーブルを作成)', "\n"; my $method = $1; *{$AUTOLOAD} = sub { shift->{$method} }; goto &$AUTOLOAD; } } 1; }; my $hoge = Hoge->new( { name => 'okamura', lang => 'ja' } ); print $hoge->name, "\n"; print $hoge->name, "\n"; print $hoge->name, "\n"; print $hoge->lang, "\n"; print $hoge->lang, "\n"; print $hoge->lang, "\n";
実行
:!perl % (初めて呼ばれたのでシンボルテーブルを作成) okamura okamura okamura (初めて呼ばれたのでシンボルテーブルを作成) ja ja ja
ここで使っているgoto文ですが、引数が&NAMEです。
% perldoc -f goto
あまり使う事のないgotoですが、引数が&NAMEのものは特殊なのです。これはAUTOLOADで使われる前提なのですが、AUTOLOADメソッドでgoto &$AUTOLOAD;を実行するともう一度AUTOLOADを呼び出すのですが、その際に$AUTOLOADに呼び出し元としてHoge::AUTOLOADを格納することになるのか、といったらそうならないでHoge::nameとかを格納します、という使われ方です*2。
と、このようにするとサブルーチンが必要となるまで定義されないというお話でした。
まとめ
AUTOLOADとgoto &NAMEは新人に説明しないでいいと思いました。社内で使ってる場所見たとこないし。。。