【Perl】”サブクラスをインスタンス化するメソッド”を動的に追加する方法を考える(その2)

投稿日: / 更新日:

前回のコード例では、インスタンス化できるサブクラス名に制約がありました。今回は、その制約を受けずに済むよう、前回のコードを改造してみたいと思います。

改造後のメインクラスは以下のとおりです。なお、改造前のコードにあったsingletonの処理は実は不完全で、コードの目的から言えば、本来はサブクラス毎にインスタンスを保持しなければならないのですが、今回はトピックから外れるため削除しました。

改造前のコードにあったAUTOLOADサブルーチンは、不要なため削除しました。代わりにBEGINブロック内で、@INC内に存在する全てのサブクラスをModule::Findモジュールのfindallmod関数を使用して検索し、見つかったサブクラス名を加工してインスタンス化のためのメソッドを生成するとともに、前回同様クロージャを使用してパッケージのシンボルテーブルに登録しています。なお、今回はAUTOLOADを使用せず、メソッドは呼び出し時にシンボルテーブルに存在している必要があるため、BEGINブロック内でコンパイル時に実行するようにしています。ちなみにあまり知られていないことですが、Perlではプログラムの実行前に、ソースコードがメモリ上でバイトコードへコンパイルされます。そのコンパイルがあまりにも高速に実行されるため、「Perlではソースコードがそのまま逐次実行される」という誤解が一般に広まっているという悲しい事実があります。

メインクラスの改造後は、サブクラスとテストコードを実装します。今回は、前回使用したサブクラスに加えて、クラス名がパスカルケースになっていないサブクラスを一つ追加し、改造後のロジックに問題がないかどうかを確認します。

なお、テストコードのうち最後のテスト項目について、メインクラスがAUTOLOADを使用しなくなったことにより、例外として送出されるメッセージを「メソッドが見つからない」という内容に変更しています。

テストコードの実行結果は以下のとおりです。

全て、問題なく動作することが確認できました。これで、以後はサブクラスをいくらアドオンしてもメインクラスに手を加える必要はなく、モジュールのメンテナンスがラクになります。また、モジュールの使用者はメインクラスだけをuseすれば済むため、大量のuse文を書く必要から解放されます。

以上、Perlに関するトピックをご紹介しました。

最新情報発信中

Twitterやメルマガでも、Hinemosの保守、
開発、導入、構築やカスタマイズ等の
お役立ち情報を発信しています。
是非ご登録ください。