=encoding utf8 =pod =head1 題名 Moose::Manual::Construction - Mooseを使ったオブジェクトの生成(と破棄) =head1 コンストラクタはどこにありますか B<自分のクラスにはCメソッドを定義しないでください!> CしたクラスはLのサブクラスになるのですが、CメソッドはこのLが用意してくれます。Lのおすすめ通りにクラスを不変化した場合は、そのクラス専用のCメソッドがクラスの中に実際に「インライン展開」されます。 =head1 オブジェクトの生成とアトリビュート Mooseが提供するコンストラクタはアトリビュートに対応する(実際にはアトリビュートのCに対応する)名前付きパラメータのハッシュないしハッシュリファレンスを受け付けます。これもまたMooseを使うとクラスが「どのように」実装されているか心配しなくてよくなる理由のひとつです。クラスを定義しさえすればオブジェクトを生成できるようになるのです! =head1 オブジェクト生成時の割り込み Mooseを使うとオブジェクト生成時に割り込みをかけることもできます(オブジェクトの状態を検証したり、ログを取ったり、おそらくハッシュ(リファレンス)以外のコンストラクタ引数を許すようにもできます)。そうする場合は、CメソッドやCメソッドを作ってください。 これらのメソッドがクラスに存在している場合、Mooseはオブジェクト生成プロセスの途中でこれらのメソッドを呼ぶよう手配してくれます。 =head2 BUILDARGS Cメソッドは、オブジェクトが生成される「前に」、クラスメソッドとして呼ばれます。Cメソッドは、Cに渡されたすべての引数を「そのままの形で」受け取り、ハッシュリファレンスを返すことが期待されています。このハッシュリファレンスはオブジェクトを生成するときに使うので、アトリビュート名(というかC)に対応したキーを入れておくようにしてください。 Cは、ハッシュ(リファレンス)以外の呼び出し方に対応させるときによく使われます。たとえば、PersonクラスはC<< Person->new($ssn) >>のように社会保障番号ひとつで呼べるようにしたい場合があるかもしれません。 この場合、Cメソッドがないと、Mooseは(ハッシュまたはハッシュリファレンスを期待しているので)エラーを発生させますが、Cメソッドを使うとこの呼び出し方に対応できます。 around BUILDARGS { my $orig = shift; my $class = shift; if ( @_ == 1 && ! ref $_[0] ) { return $clas->$orig( ssn => $_[0] ); } else { return $class->$orig(@_); } } C<$class->$orig>を呼んでいることに注意してください。これは親クラスのメソッドを呼び出すことによりLにデフォルトで用意されているCを呼ぶものです。このメソッドを使うとハッシュリファレンスとただのハッシュを区別してくれます。 =head2 BUILD Cメソッドはオブジェクトが生成された「あとに」呼ばれます。Cメソッドの使い方はいくつかありますが、もっともよくあるのは、オブジェクトの状態が有効かどうかチェックするものです(型を使えば個々のアトリビュートの検証はできますが、オブジェクト全体の状態についてはその方法では検証できません)。 sub BUILD { my $self = shift; if ( $self->country_of_residence eq 'USA' ) { die 'All US residents must have an SSN' unless $self->has_ssn; } } Cメソッドのほかの使い方としては、オブジェクトを生成したときのログ取りやトラッキングがあげられます。 sub BUILD { my $self = shift; debug( 'Made a new person - SSN = ', $self->ssn, ); } ここでは使用していませんが、Cメソッドは作成されたオブジェクトだけではなく、newに渡された元の引数(もしCをオーバーライドしているなら、Cの戻り値)が渡されます。デフォルトで提供されている初期化や型変換の仕組み以外の操作が必要な場合は便利かもしれません。 =head3 BUILDと親クラス 継承階層に複数のCメソッドがある場合、Perlのふつうのメソッドとは相互作用の仕方が異なるので、B<決してC<< $self->SUPER::BUILD >>は呼ばないようにしてください。> Mooseは、オブジェクトを生成するとき、階層内にあるすべてのCメソッドを「親から子の順番で」呼ぶよう手配します(最初は驚くかもしれませんが、通常のメソッド継承の順番とは逆なのです)。 このようになっているのは、Cメソッドはクラスの制約の特殊性を増すことにしか使えないため、もっとも抽象的なCから呼んでいく方が理にかなっているからです(なお、Perl 6もそのようになっています)。 =head1 オブジェクトの破棄 Mooseを使うと、オブジェクトを破棄するときもCメソッドで割り込みをかけられます。Cの場合と同じく、明示的にC<< $self->SUPER::DEMOLISH >>を呼ぶことは決してしないでください。Mooseは階層内のすべてのCメソッドを、もっとも具体的なクラスからもっとも抽象的なクラスの順に呼ぶよう手配します。 それぞれのCメソッドは1つの引数をうけとります。 ただし、たいていの場合はPerlに組み込まれているガベージコレクションで十分です。Cメソッドを用意する必要はありません。 =head2 オブジェクト破棄時のエラー処理 オブジェクト破棄時の動作とPerlのグローバル変数C<$@>やC<$?>との連携は時々わかりにくい副作用を及ぼします。 オブジェクト破棄時にMooseは必ずC<$?>をローカル化します。これはもしデストラクタでCを使用してても、Cの値は保護されるということになります。 オブジェクト破棄時にMooseは必ずC<$@>もローカル化します。ただし、オブジェクトのCメソッドが例外を投げた場合はMooseは明示的に再度同じ例外を投げます。 もしこの動作仕様があなたの要求と会わない場合は、デフォルトのLの代わりに自前のCメソッドを用意する必要があります。このようにすると例えばC<$@>の値を保持したままオブジェクト破棄時に起こったエラーのスタックをキャプチャすることができます。 =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