=encoding utf8 =pod =head1 題名 Moose::Cookbook::Basics::Recipe11 - Mooseを使っていないベースクラスを拡張する =head1 概要 package My::DateTime; use Moose; extends qw( DateTime Moose::Object ); use DateTime::Calendar::Mayan; has 'mayan_date' => ( is => 'ro', isa => 'DateTime::Calendar::Mayan', init_arg => undef, lazy => 1, builder => '_build_mayan_date', clearer => '_clear_mayan_date', predicate => 'has_mayan_date', ); sub new { my $class = shift; my $obj = $class->SUPER::new(@_); return $class->meta->new_object( __INSTANCE__ => $obj, @_, ); } after 'set' => sub { $_[0]->_clear_mayan_date; }; sub _build_mayan_date { DateTime::Calendar::Mayan->from_object( object => $_[0] ); } =head1 本文 このレシピではMooseを利用してMooseベースではない親クラスをサブクラス化する方法を説明します。このレシピでうまく行くのは親クラスがblessされたハッシュリファレンスの場合のみです。親クラスがちょっと変わったことをしている場合はLを試してみてください。 また、Lを試してみてもよいかもしれません。これを使うと面倒な作業はすべてやってくれます。 いくつか注釈を入れておきたい箇所があります。 use Moose; extends qw( DateTime Moose::Object ); まず、いつものようにCします。こうするとアトリビュートを宣言したり、おなじみのシュガー関数をすべて利用できるようになります。 Cの宣言にはLだけでなく、明示的にLを入れておきます。こうすると、CのようにLが提供しているメソッドも使えるようになります。 コンストラクタにはMooseを使っていない親クラスを使うときに特有のハック/パターン(ハックたん?)が見られます。 sub new { my $class = shift; my $obj = $class->SUPER::new(@_); return $class->meta->new_object( __INSTANCE__ => $obj, @_, ); } ここでは明示的にC<< $class->meta->new_object >>を呼んで、作成済みのオブジェクトをC<__INSTANCE__>キーとともに渡しています。内部的にはMooseが既存のオブジェクトを受け取り、あればサブクラスで定義されているアトリビュートの初期化を行います。 Cモディファイアは期待通りの動作をします。CがMooseを使っていない親クラスで定義されていても問題ありません。 =head1 まとめ Mooseは、ここで紹介したパターンにしたがえば、Mooseを使っていないクラスともうまく共存できます。アトリビュートの宣言、メソッドモディファイア、(新しいアトリビュートの)型制約、ロールといったMooseの力は、サブクラスの中でもすべて利用できます。 ただし、親クラスの「アトリビュート」はMooseのアトリビュートではありませんから、簡単にはオーバーライドできません。また、コンストラクタをインライン展開することもできません。メタクラスのオブジェクトコンストラクタを明示的に利用する必要があるためです。 =head1 作者 Dave Rolsky Eautarch@urth.orgE =head1 COPYRIGHT AND LICENSE Copyright 2009 by Infinity Interactive, Inc. L This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut