useとかimportとかについて
Maypoleのソースコードを読んでいて、どうしてもわからないことがあったのだけれどやっとわかってきたのでメモ。
Maypoleでアプリケーションを書くときはMaypole::Applicationをuseして、
package MyApp; use Maypole::Application; MyApp->setup();
とかします。継承ではなくてuseです。じゃあsetupってメソッドはどこから出てきたのだ!
答えはMaypole::Application::importにありました。これもよくわからなくて、ソースツリーをgrepしてもimportを呼び出してるところはないし、なんだろう?と思っていたのですが、プログラミングPerl〈VOLUME1〉とかオブジェクト指向Perlマスターコース―オブジェクト指向の概念とPerlによる実装方法とかをひっくり返していたら判明しました。importはuseしたときにPerlから自動的に呼び出されるのですね。useするとPerlが何をするのかってのはオブジェクト指向Perlの71ページとか76ページとかに書いてあります。importには引数としてモジュールの名前とuseステートメントの最後に指定したすべての引数のリストが渡されます。importを使ってなにかする代表的なものにはExporterモジュールがあるようです。なるほどね。
オブジェクト指向Perlの76ページによると、
Exporterを使用することによって、importの代表的な処理、すなわちモジュールの名前空間から呼び出し元の名前空間にパッケージ変数およびサブルーチンをインポートする処理が容易になる。
とのこと。ただ、クラスから変数またはサブルーチンをエクスポートすることはオブジェクト指向のカプセルか原理に反するので云々、ということも書いてあります。
さて、Maypole::Applicationのimportでも大体において似たようなことをしています。
- フロントエンドの決定(Apache::MVC、CGI::Maypoleなど)と@ISAへのpush
- useで指定された引数リストの解析
- Universal::requireによるプラグインモジュールのロード
- 呼び出し元の継承ツリー(@ISA)にプラグインモジュールと自分自身をpush
- Maypole::Configのnewと呼び出し元への設定
謎が氷解した。
1番目と4番目ですね。1番目で継承するフロントエンドモジュールはMaypoleモジュールを継承しているので、これでsetupメソッドも継承されます。そしてこのモジュール自身が呼び出し元の継承ツリーに追加されるので、
MyApp->setup();
ってできるのだ!
呼び出された(useされた)側のモジュールが自分自身を呼び出し元の継承ツリーに追加してしまうとか、なんかすごいもの見たなって感じ。勉強になりました。
ここっすね。
no strict 'refs'; push @{"${caller}::ISA"}, @plugin_modules, $class;
-
- -