=encoding utf8 =pod =head1 題名 Moose::Cookbook::Basics::Recipe10 - BUILDARGSとBUILDを使ってオブジェクトの生成に割り込む =head1 概要 package Person; has 'ssn' => ( is => 'ro', isa => 'Str', predicate => 'has_ssn', ); has 'country_of_residence' => ( is => 'ro', isa => 'Str', default => 'usa' ); has 'first_name' => ( is => 'ro', isa => 'Str', ); has 'last_name' => ( is => 'ro', isa => 'Str', ); around BUILDARGS => sub { my $orig = shift; my $class = shift; if ( @_ == 1 && ! ref $_[0] ) { return $class->orig( ssn => $_[0] ); } else { return $class->$orig(@_); } } sub BUILD { my $self = shift; if ( $self->country_of_residence eq 'usa' ) { die 'Cannot create a Person who lives in the USA without an ssn.' unless $self->has_ssn; } } =head1 本文 このレシピではCとCの使い方を説明します。これらのメソッドを定義すると、Cをオーバーライドしなくてもオブジェクトの生成プロセスに割り込むことができます。 Cメソッドが呼ばれるのはオブジェクトが生成される「前」です。これはクラスメソッドとして呼ばれ、Cメソッドに渡されるすべてのパラメータを受け取ります。Cメソッドはその引数に何らかの処理をして、ハッシュリファレンスを返すことが期待されています。ハッシュの各キーはアトリビュートのCでなければなりません。 Cの主な目的は、クラスが名前付き引数以外のものを受け取れるようにすることです。このCクラスの場合は引数が社会保障番号ひとつだけでも呼べるようにしています。 my $person = Person->new('123-45-6789'); 今回のCのポイントはこの条件文です。 if ( @_ == 1 && ! ref $_[0] ) { $class->$orig( ssn => $_[0] ); } Mooseのコンストラクタは、デフォルトではキーと値のペアからなるリストか、ハッシュリファレンスを受け取るようになっているので、リファレンスでないことを確認してからでないとC<$_[0]>が社会保障番号であると想定することはできません。 親クラスのC<< BUILDARGS >>を呼んでいるのは、それ以外のすべてのケースに対応するためです。自分でCメソッドを実装する場合はかならずこのようにしておいてください。Lにもハッシュリファレンスやキーと値のペアのリストを処理する独自のCメソッドが用意されているためです。 Cメソッドが呼ばれるのはオブジェクトが生成された「あと」、呼び出し元にオブジェクトを返す前です。Cメソッドを使うと全体的なオブジェクトの状態をチェックできます。Cメソッドは個々のアトリビュートの型制約だけでは表現できないロジックを入れておくのに便利です。 Cクラスの場合はCとCという2つのアトリビュートの関係をチェックする必要があります。オブジェクトが論理的に首尾一貫していない場合は例外が発生します。 =head1 検討課題 このレシピではすべてのアトリビュートが読み取り専用なのでかなり単純になっていますが、Cアトリビュートが設定可能だったら、新しい居住国がCだったときにCが設定されているかチェックする必要が出てきます(このようなチェックはCモディファイアを使えば実現できるかもしれません)。 =head1 まとめ これまで何度もMooseのクラスではCをオーバーライドしないようにと言ってきました。このレシピでは、CをオーバーライドしなくてもCとCを使えばオブジェクトの生成に割り込めることを紹介しました。 Cメソッドを使うと、Mooseに組み込まれているコンストラクタのパラメータ処理を拡張できます。Cメソッドを使うと、オブジェクト生成後にオブジェクト全体にかかわる論理的な制約を実装できます。 =head1 作者 Dave Rolsky Eautarch@urth.orgE =head1 COPYRIGHT AND LICENSE Copyright 2006-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