題名¶
Moose::Cookbook::Basics::Recipe10 - BUILDARGSとBUILDを使ってオブジェクトの生成に割り込む
概要¶
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;
}
}
本文¶
このレシピではBUILDARGS
とBUILD
の使い方を説明します。これらのメソッドを定義すると、new
をオーバーライドしなくてもオブジェクトの生成プロセスに割り込むことができます。
BUILDARGS
メソッドが呼ばれるのはオブジェクトが生成される「前」です。これはクラスメソッドとして呼ばれ、new
メソッドに渡されるすべてのパラメータを受け取ります。BUILDARGS
メソッドはその引数に何らかの処理をして、ハッシュリファレンスを返すことが期待されています。ハッシュの各キーはアトリビュートのinit_arg
でなければなりません。
BUILDARGS
の主な目的は、クラスが名前付き引数以外のものを受け取れるようにすることです。このPerson
クラスの場合は引数が社会保障番号ひとつだけでも呼べるようにしています。
my $person = Person->new('123-45-6789');
今回のBUILDARGS
のポイントはこの条件文です。
if ( @_ == 1 && ! ref $_[0] ) {
$class->$orig( ssn => $_[0] );
}
Mooseのコンストラクタは、デフォルトではキーと値のペアからなるリストか、ハッシュリファレンスを受け取るようになっているので、リファレンスでないことを確認してからでないと$_[0]
が社会保障番号であると想定することはできません。
親クラスのBUILDARGS
を呼んでいるのは、それ以外のすべてのケースに対応するためです。自分でBUILDARGS
メソッドを実装する場合はかならずこのようにしておいてください。Moose::Objectにもハッシュリファレンスやキーと値のペアのリストを処理する独自のBUILDARGS
メソッドが用意されているためです。
BUILD
メソッドが呼ばれるのはオブジェクトが生成された「あと」、呼び出し元にオブジェクトを返す前です。BUILD
メソッドを使うと全体的なオブジェクトの状態をチェックできます。BUILD
メソッドは個々のアトリビュートの型制約だけでは表現できないロジックを入れておくのに便利です。
Person
クラスの場合はssn
とcountry_of_residence
という2つのアトリビュートの関係をチェックする必要があります。オブジェクトが論理的に首尾一貫していない場合は例外が発生します。
検討課題¶
このレシピではすべてのアトリビュートが読み取り専用なのでかなり単純になっていますが、country_of_residence
アトリビュートが設定可能だったら、新しい居住国がusa
だったときにssn
が設定されているかチェックする必要が出てきます(このようなチェックはbefore
モディファイアを使えば実現できるかもしれません)。
まとめ¶
これまで何度もMooseのクラスではnew
をオーバーライドしないようにと言ってきました。このレシピでは、new
をオーバーライドしなくてもBUILDARGS
とBUILD
を使えばオブジェクトの生成に割り込めることを紹介しました。
BUILDARGS
メソッドを使うと、Mooseに組み込まれているコンストラクタのパラメータ処理を拡張できます。BUILD
メソッドを使うと、オブジェクト生成後にオブジェクト全体にかかわる論理的な制約を実装できます。
作者¶
Dave Rolsky <autarch@urth.org>
コピーライト & ライセンス¶
Copyright 2006-2009 by Infinity Interactive, Inc.
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.