Moose > Moose::Cookbook::Extending::Recipe3

題名

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

概要

  package MyApp::Base;
  use Moose;

  extends 'Moose::Object';

  before 'new' => sub { warn "Making a new " . $_[0] };

  no Moose;

  package MyApp::UseMyBase;
  use Moose ();
  use Moose::Exporter;

  Moose::Exporter->setup_import_methods( also => 'Moose' );

  sub init_meta {
      shift;
      return Moose->init_meta( @_, base_class => 'MyApp::Base' );
  }

本文

よくある拡張モジュールとしては、ベースクラスの代用品を提供するものがあります。MyApp::Baseを用意して、アプリケーションのすべてのクラスにextends 'MyApp::Base'を追加するのもひとつのやり方ですが、これはかなり面倒です。そのかわりにMyApp::BaseをベースオブジェクトクラスにしてくれるMooseもどきのモジュールを作りましょう。

そうすれば、use Mooseと書くかわりにuse MyApp::UseMyBaseと書くことができるようになります。

この例のベースクラスは新しいオブジェクトを生成するたびにデバッグ用の情報を出力しますが、みなさんが自分でベースクラスを作るときはもっとおもしろい使い方を考えてみてください。

ここではMoose::Exporterの魔法を利用します。Moose::Exporter->setup_import_methods( also => 'Moose' )を呼ぶと、importメソッドとunimportメソッドを用意してくれます。also => 'Moose'の部分は、Mooseがエクスポートするものはすべてエクスポートしてほしい、という意味です。

ここで作成されたimportメソッドは、私たちのinit_metaメソッドを呼び出し、for_caller => $callerという引数を渡します。この$callerは、実際にはじめてimportを実行したクラスになります。

Moose::ExporterのAPIについてはMoose::Exporterのドキュメントをご覧ください。

MyApp::UseMyBaseを使う

実際に私たちの新しいベースクラスを使いたいときは単にMooseの「かわり」にMyApp::UseMyBaseをuseしてください。これで、Mooseのすべてのシュガー関数と、私たちの新しいベースクラスが利用できるようになります。

  package Foo;

  use MyApp::UseMyBase;

  has 'size' => ( is => 'rw' );

  no MyApp::UseMyBase;

まとめ

単純なベースクラスだったわりにはずいぶん大げさな魔法を使いましたが、ベースクラスを拡張するモジュールにはよくメタクラスのトレートを合成したくなるものですし、そのような時にはこのテクニックが役に立ちます。

作者

Dave Rolsky <autarch@urth.org>

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

Copyright 2006-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.