Moose > Moose::Cookbook::Meta::Recipe5

題名

Moose::Cookbook::Meta::Recipe5 - メタクラスのトレートとしての「table」アトリビュート

概要

  package MyApp::Meta::Class::Trait::HasTable;
  use Moose::Role;

  has table => (
      is  => 'rw',
      isa => 'Str',
  );

  package Moose::Meta::Class::Custom::Trait::HasTable;
  sub register_implementation { 'MyApp::Meta::Class::Trait::HasTable' }

  package MyApp::User;
  use Moose -traits => 'HasTable';

  __PACKAGE__->meta->table('User');

本文

このレシピでは、Moose::Cookbook::Meta::Recipe4で説明したtableというメタクラスアトリビュートをメタクラスのトレートとして実装します。トレートはMoose::Cookbook::Meta::Recipe3でも見たように単なるロールに過ぎません。

トレートを利用する利点は、複数のトレートの合成が簡単にできることです。メタクラスのサブクラスを複数合成する場合、さらにもうひとつサブクラスを作る必要がありますが、トレートの場合は、メタクラスに組み込む部分はMooseが面倒を見てくれます。

実際にメタクラスのトレートを利用してみる

このトレートをメタクラスに組み込んでしまえば、見た目はMoose::Cookbook::Meta::Recipe4で見た例とまったく同じになります。

  my $table = MyApp::User->meta->table;

  # the safe version
  $table = MyApp::User->meta->table
      if MyApp::User->meta->meta->can('does')
         and MyApp::User->meta->meta->does('MyApp::Meta::Class');

安全なバージョンは少し複雑です。メタクラスオブジェクトのメタクラスにdoesメソッドがあるかを確認しなければなりません。doesメソッドがあれば、メタクラスに特定のロールが組み込まれているか確認できます。

もっと簡単に、こう書くこともできます。

  $table = MyApp::User->meta->table
      if MyApp::User->meta->can('table');

理屈の上ではこちらはやや不正確です。メタクラスは「別の」ロールからtableメソッドをもらっている可能性がありますので。ただし、実用上、その手の問題に行き当たることはまずないでしょう。

参照

Moose::Cookbook::Meta::Recipe3 - アトリビュートのトレートを利用したラベルの実装

Moose::Cookbook::Meta::Recipe4 - メタクラスに「table」アトリビュートを追加する

作者

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.