Moose > Moose::Cookbook::Basics::Recipe8

題名

Moose::Cookbook::Basics::Recipe8 - ビルダーメソッドとlazy_build

概要

  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 );
  }

本文

この例は、Moose::Cookbook::Basics::Recipe3を読んだ方ならほとんど同じもののように見えることでしょう。実際、ここでしたのはアトリビュートのdefaultパラメータをbuilderで置き換えたことだけです。

この例に限っていえば、defaultbuilderオプションはまったく同じ働きをしています。leftないしrightアトリビュートを読み込もうとすると、ビルダーメソッドが呼ばれてアトリビュートが初期化されるわけです。

注意したいのは、Mooseは、「そのアトリビュートが定義されているオブジェクトの」ビルダーメソッドを呼ぶ、ということ。例をあげましょう。

  my $tree = BinaryTree->new();

  my $left = $tree->left();

$tree->left()が呼ばれると、Mooseは$tree->_build_child_tree()を呼んでleftアトリビュートの初期化を行います。あらかじめもとのコンストラクタにleftが渡されていた場合は、ビルダーは呼ばれません。

defaultbuilderにはいくつか違いがあります。特筆に値するものとしては、ビルダーはサブクラス化が可能であることと、ロールから合成できることがあげられます。詳しくはMoose::Manual::Attributesをご覧ください。

lazy_buildによるショートカット

アトリビュートのオプションを一度にまとめて指定するシンタックスシュガーとして、lazy_buildというアトリビュートオプションを使うこともできます。

  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',
  );

アトリビュートがアンダースコア(下線)で始まる場合、predicateclearerについてはMooseが気を利かせて、期待通りにメソッド名がアンダースコアで始まるようにしてくれます。builderメソッドについては「常に」アンダースコアで始まります。

lazy_buildの詳細についてはMoose::Manual::Attributesをご覧ください。

まとめ

builderオプションは、defaultの機能をよりオブジェクト指向らしくしたものです。また、デフォルト値を生成するコードを明確に定義されたメソッドに分離してくれます。アトリビュートの定義に無名サブルーチンを混ぜると、非常に見苦しい、理解しづらいものになることがあります。

作者

Dave Rolsky <autarch@urth.org>

コピーライト & ライセンス

Copyright 2006-2009 by Infinity Interactive, Inc.

http://www.iinteractive.com

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.