Don't use base.pm, use parent.pm instead!
「使っちゃいけない標準モジュール」*1の反響を見ていると、baseが非奨励ということに驚かれた方が少なくありませんでした。そこで、baseについて補足します。
まずbase.pmのドキュメントの最初の文は以下のようになっています。
Unless you are using the fields pragma, consider this module discouraged in favor of the lighter-weight parent.
(拙訳: fieldsプラグマを使用しているのでないかぎり、このモジュールは勧められない。かわりに軽量なparent.pmを使う方がよい。)
fieldsプラグマは、ハッシュリファレンスのキーを固定したオブジェクトを作成するための機能ですが、あまり一般的ではないためここでは解説しません。特に理由がない限り、ここは素直に忠告に従った方がいいでしょう。parentはPerl 5.10から標準モジュールとなっていますが、CPANにもあります。特に依存のない小さなpure Perlモジュールなので、インストールは簡単です。
ただし、parentはbaseと少しだけインターフェイスが違います。baseは指定したモジュールが空でなければそのモジュールのロードを試み、ロードに失敗しても処理を続けます*2。一方parentは常にロードを試み、モジュールのロードに失敗するとdieします。これがparentの利点です。ロードすべきモジュールをロードできないというのは致命的なエラーであり、プログラムの実行は中止する方がいいでしょう。もしロードが必要ないなら、-norequireというオプションを渡します。
{ package Foo; use parent qw(HTML::Parser); # モジュールを確実にロードする } { package Bar; use parent -norequire => qw(Foo); # モジュールのロードは試みない }
さて、baseにはさらに一つバグが発見されています。このバグによって以下のコードはエラーになります。parentであれば問題は起こりません。
{ package Foo; use LWP::UserAgent; use base qw(HTML::Parser); } Foo->new(); # Can't locate object method "new" via package "Foo" at ...
これはbaseの「対象のパッケージが空であればロードを試みる」という処理の「パッケージが空であれば」というルーチンにバグがあるため、LWP::UserAgentをロードするだけでHTML::Parserのパッケージが空でないように見えてしまうからです。これにより、use base qw(HTML::Parser)
としているすべてのモジュールは、LWP::UserAgentの前にロードしなければならないのです。具体的には、HTML::StickyQueryのversion 0.12以前のバージョンでこのバグに遭遇し、baseをparentで置き換えた0.13のリリースとなりました。
このバグはbaseにパッチをあてれば修正できますが、parentに置き換える方が容易でしょう。