Moose > Moose::Cookbook::Extending::Recipe2

題名

Moose::Cookbook::Extending::Recipe2 - オブジェクトのベースクラス用のロールを用意する

概要

  package MooseX::Debugging;

  use Moose::Exporter;

  Moose::Exporter->setup_import_methods;

  Moose::Exporter->setup_import_methods(
      base_class_roles => ['MooseX::Debugging::Role::Object'],
  );

  package MooseX::Debugging::Role::Object;

  use Moose::Role;

  after 'BUILD' => sub {
      my $self = shift;

      warn "Made a new " . ref $self . " object\n";
  };

本文

この例では、オブジェクトのベースクラス用のロールを用意して、簡単なデバッグ用の出力を追加します。このロールは、オブジェクトを生成するたびにそのオブジェクトの種類を知らせる警告を吐きます。

もちろん本物のデバッグ用ロールではもっと興味深いことをするものですが、このレシピで大切なのはこのロールをどう組み込むかということだけです。

今回は、Moose::ExporterMoose::Util::MetaRoleを組み合わせて、モジュールがuse MooseX::Debuggingしたときにはかならずベースオブジェクトのクラスにデバッグ用ロールが自動的に組み込まれるようにしています。

いくつかのコードについてはもっと細かく見ていきましょう。

  Moose::Exporter->setup_import_methods(
      base_class_roles => ['MooseX::Debugging::Role::Object'],
  );

これはMooseX::Debuggingパッケージにimportメソッドを用意するものです。ここでは実際になにかをエクスポートするわけではないのでsetup_import_methodsにはパラメータを渡していませんが、importメソッドがないと私たちのinit_metaメソッドが確実に呼ばれることは保証できないのです。なおinit_metaメソッド自体はbase_class_rolesオプションを指定することにより、setup_import_methodsによって自動的に生成されています。生成されたinit_metaMoose::Util::MetaRole::apply_base_class_rolesを呼び出します。

それから、私たちのinit_metaメソッドにはこのような行があります。

      Moose->init_meta(%options);

これはほとんどどんな拡張モジュールでも使う決まり文句のようなものです。こうしておくと、呼び出し元のクラスにトレートを追加する「前」に通常のMooseのメタクラスを確実に用意できるようになります。

Moose->init_metaメソッドを使えば確実に呼び出し元のクラスにまともなメタクラスを用意できますが、拡張モジュールの中ではそのロジックを繰り返したくはありません。Moose->init_metaがすでに呼ばれていた(呼び出し元のクラスが私たちの拡張モジュールをuseする前にuse Mooseしていた)場合、2度目のMoose->init_metaは実質的には無効になります。

作者

Dave Rolsky <autarch@urth.org>

コピーライト & ライセンス

Copyright 2009 by Infinity Interactive, Inc.

http://www.iinteractive.com

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.