2012-03-02 7 views
14

builderを使用すると、サブクラスが属性のデフォルトを簡単に上書きできるようになり、役割はrequireになります。また、これはそうのようなdefaultを使用して達成することができます。Moose "builder" vs "default"

has 'foo' => 
    is  => 'rw', 
    isa  => 'Str', 
    default => sub { $_[0]->_build_foo }; 

私は認識していないよbuilderを使用する更なる利点がある場合、私は思ったんだけど?私はいくつかの自分を作ってみた:あなたはfoo_build_foo

  • builderによって構築されていることをイントロスペクションできるよう

    • builderは、宣言され、それが少し速く
    • builder行うサブルーチンラッパーが使用することができます排除役に立つlazy_build

    明確にするためにUPDATE、これは約default一般的にbuilderしかしbuilder => '_build_foo'default => sub { $_[0]->_build_foo }対ではありません。

  • 答えて

    12

    私はすでにあなた自身の質問に答えていると思います。 builderを使用すると、後でバインドすることができます。これは、サブクラス化されることを意図した役割とクラスでうまくいきます。もしビルダーがかなり長いのであれば、それはまた価値があります - 私は決してを長さ以上の属性定義に入れることはありません。実際の機能上の違いはありません。 defaultは簡単にbuilderをエミュレートできますが、結果はあまり美しくありません。

    +0

    なぜ 'default => \&builder'はそれらすべてのことをしないのですか? – ikegami

    +2

    @ikegami '\&builder'は現在のパッケージの'&builder'に解決されるためです。新しい 'builder 'を提供するサブクラスは、' has' + attr '=> builder => \&builder'をもう一度やり直す必要があります。 OTOH 'builder => 'builder'は実行時に解決されます。 – hobbs

    +0

    対称として、サブクラスは属性を上書きして 'default'を変更することができます。これはおそらくプライベートな 'builder'メソッド名を知る必要はありません。 *両方とも*属性が 'default'または' builder'を使用しているかどうかを知る必要があります。これは一般に個人情報であり、変更される可能性があります。 Mooseの属性のデフォルトの動作をオーバーライドするのは問題があるため、そのデフォルト動作がどのように実装されているか、サブクラスがイントロスペクションを行う方法の詳細を公開する必要があります。 :/ – Schwern

    3

    defaultbuilderの主な違いは、1つアノンサブを呼び出し、他の名前のメソッドを呼び出すことである

    default => sub { $_[0]->_build_foo } 
    

    builder => '_build_foo' 
    

    の間に違いはありません。

    has created_time_stamp => (
        builder => '_build_created_time_stamp', 
    ); 
    
    sub _build_created_time_stamp { time() } 
    

    has created_time_stamp => (
        default => sub { time() }, 
    ); 
    

    defaultを使用して、あなたがそれを必要な場所すべてがあるように、コードをスクロール減少します。私はその理由のためにそれを使用します。それはより少ないタイピングを使用してボーナスです。

    また、ビルダーのオーバーライドをより明確にする必要があります。他の答えはこれを詐欺だと考えていますが、まだ構築されていないオブジェクトに対しても、仮想メソッドを呼び出すことは悪い習慣です。それはBUILDが対象です。

    +0

    質問は 'デフォルト=>サブについて具体的には、{$ _ [0] - > _ build_foo}' 'VSビルダー=>「_build_foo''、サブクラスはデフォルトを上書きできるように、一般的にはビルダー対デフォルトではありません。それで、追加のサブコールが必要なのです。 – Schwern

    +0

    @Schwern、なぜあなたはそれをしますか?それは何の理由もありません。まあ、たぶんどこかで 'default'を使ったのであれば一貫性があります。 – ikegami

    +2

    「なぜあなたはそれをしますか?」私が求めているのはまさにそのことです。 'builder => '_build_foo''は' default => sub {$ _ [0] - > _ build_foo} 'の構文砂糖です。もっと何かありますか? – Schwern

    4

    'builder'と 'default'を適切に使用すると、コードを読みやすく整理しやすくなります。

    「ビルダー」は、プライベートメソッドがアンダースコアで始まるプログラミングの使い慣れたパターンにも適合します。これらは方法のほとんどがある

    has things => (is => 'ro', lazy => 1, builder => 'get_things'); 
    

    :メモ化と

    sub get_things { 
        my $self = shift; 
        return +{ map { $_ => $self->price_for($_) } 
        $self->wodgets->calulate_expensive_things }; 
    

    リファクタリング:

    has json => (is => 'ro', default => sub { JSON->new }) 
    has schema => (is => 'ro', builder => '_schema' } 
    
    sub _schema { 
        my $self = shift; 
        $self->log_debug('constructing schema') if($self->debug); 
        My::App::Schema->connect($self->dsn,$self->username,$self->password) 
    } 
    

    また、ビルダーを使用すると、元のメソッドに触れずにメモ化アクセサに高価な機能をオンにすることができます私は自分のコードを明確にするためにビルダーを使いました。

    +0

    私はまた、言い換えれば、役割の属性にそれらを使用して、その役割を消費するクラスで誰かが再定義したいと思うようにしたいと思います。名前の前に '+'を付けて属性全体を再定義するよりも簡単です。 – dhoss

    +0

    残念ながら、これは 'builder'対' default'ではなく、 'default => sub {$ _ [0] - > _ build_foo}' vs 'builder => '_build_foo'です。 – Schwern

    関連する問題