=encoding utf8 =pod =head1 題名 Moose::Cookbook::Basics::Recipe8 - ビルダーメソッドとlazy_build =head1 概要 package BinaryTree; use Moose; has 'node' => (is => 'rw', isa => 'Any'); has 'parent' => ( is => 'rw', isa => 'BinaryTree', predicate => 'has_parent', weak_ref => 1, ); has 'left' => ( is => 'rw', isa => 'BinaryTree', predicate => 'has_left', lazy => 1, builder => '_build_child_tree', ); has 'right' => ( is => 'rw', isa => 'BinaryTree', predicate => 'has_right', lazy => 1, builder => '_build_child_tree', ); before 'right', 'left' => sub { my ($self, $tree) = @_; $tree->parent($self) if defined $tree; }; sub _build_child_tree { my $self = shift; return BinaryTree->new( parent => $self ); } =head1 本文 この例は、Lを読んだ方ならほとんど同じもののように見えることでしょう。実際、ここでしたのはアトリビュートのCパラメータをCで置き換えたことだけです。 この例に限っていえば、CとCオプションはまったく同じ働きをしています。CないしCアトリビュートを読み込もうとすると、ビルダーメソッドが呼ばれてアトリビュートが初期化されるわけです。 注意したいのは、Mooseは、「そのアトリビュートが定義されているオブジェクトの」ビルダーメソッドを呼ぶ、ということ。例をあげましょう。 my $tree = BinaryTree->new(); my $left = $tree->left(); C<< $tree->left() >>が呼ばれると、MooseはC<< $tree->_build_child_tree() >>を呼んでCアトリビュートの初期化を行います。あらかじめもとのコンストラクタにCが渡されていた場合は、ビルダーは呼ばれません。 CとCにはいくつか違いがあります。特筆に値するものとしては、ビルダーはサブクラス化が可能であることと、ロールから合成できることがあげられます。詳しくはLをご覧ください。 =head2 lazy_buildによるショートカット アトリビュートのオプションを一度にまとめて指定するシンタックスシュガーとして、Cというアトリビュートオプションを使うこともできます。 has 'animal' => ( is => 'ro', isa => 'Animal', lazy_build => 1, ); これは、次の書き方を簡略化したものです。 has 'animal' => ( is => 'ro', isa => 'Animal', required => 1, lazy => 1, builder => '_build_animal', predicate => 'has_animal', clearer => 'clear_animal', ); アトリビュートがアンダースコア(下線)で始まる場合、CとCについてはMooseが気を利かせて、期待通りにメソッド名がアンダースコアで始まるようにしてくれます。Cメソッドについては「常に」アンダースコアで始まります。 Cの詳細についてはLをご覧ください。 =head1 まとめ Cオプションは、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