AUTOLOADでメソッドを作ってるとcanで引っかからない
約2ヶ月前、can()はどのインスタンスでもできるんだよなーと思って、以下のコードを実行した。
use CGI; my $q = CGI->new; if ($q->can('header')) { print "CGI can 'header'.\n"; } else { print "CGI can't 'header'.\n"; }
実行。
CGI can't 'header'.
あれーなんでtrueの方に行かないんだー?、と放置していたのが、今日ようやく分かったのでメモ。
CGI.pmのバージョンは「3.05」。
CGI.pmはもうどんなものがきても対応できるように書かれていて、その分読み込みコストも相当みたい。
それを軽くするために、メソッドの多くが実行時にAUTOLOADを通して作られていた。
can()は、いまあるメソッドから探してくるために、$q->can('header')だけでは、そんなメソッドありませんと言われたのだ。
だから、一回でもメソッドを使えば、can()はそれを見つけてくれる。
use CGI; my $q = CGI->new; $q->header; # void if ($q->can('header')) { print "CGI can 'header'.\n"; } else { print "CGI can't 'header'.\n"; }
CGI can 'header'.
ちなみに1。
sub AUTOLOAD で使われている _compile() が、実際に eval() でコードをランタイムで作っているようだけれど、それだけじゃなくて、やっぱり色々しているなーという印象。
ちなみに2。
最新のバージョン「3.49」でしか確認していないけれど、こちらでは最初からcan()が動いた。
オーバーライドされて、can()のときにも _compile() が起動されるようになっていた。