2010-11-19 37 views
6

我在駝鹿對象中有一堆懶惰的特徵。我該如何讓所有的懶惰駝鹿功能建成?

一些建造者需要一些時間來完成。

我想喚起所有的建設者(轉儲「bomplete」對象)。 我可以一次構建所有懶惰功能,還是必須手動調用每個功能才能使其生成器運行?

+1

你不應該使用'default'嗎?我認爲'lazy'的意思是推遲創建屬性值直到第一次使用。如果你需要在對象構造中設置所有屬性,'default'似乎更有用。或者,你可以提供你自己的'BUILD'方法。 – 2010-11-19 14:05:47

+0

這是一個相當常見的習慣用法,它有一些體面的原因。 – hobbs 2010-11-19 15:22:57

+0

基本上,您可以在'BUILD'中完成所有工作,但是每個屬性都有一個方法會更好。如果你打算爲每個屬性計算一個方法的值,那麼它也可能是一個構建器。但是如果構建器要訪問其他屬性,那麼構建的屬性需要很懶,以確保它們已被初始化。並且沒有「懶惰,但只有一點點」懶惰「屬性選項:) – hobbs 2010-11-19 15:28:57

回答

6

如果您希望使用構建器具有「惰性」屬性,但要確保其值在new返回之前構建,通常要做的是調用BUILD中的訪問器。

sub BUILD { 
    my ($self) = @_; 

    $self->foo; 
    $self->bar; 
} 

就足以完成工作,但它可能是最好的加註釋以及解釋這種顯然無用代碼的人誰不知道這個成語。

3

也許你可以使用meta類來獲得'lazy'屬性列表。例如:

package Test; 

use Moose; 


has ['attr1', 'attr2'] => (is => 'rw', lazy_build => 1); 
has ['attr3', 'attr4'] => (is => 'rw',); 

sub BUILD { 
    my $self = shift; 


    my $meta = $self->meta; 

     foreach my $attribute_name (sort $meta->get_attribute_list) { 

     my $attribute = $meta->get_attribute($attribute_name); 

     if ($attribute->has_builder) { 
      my $code = $self->can($attribute_name); 
      $self->$code; 

     } 
    } 

} 


    sub _build_attr1 { 1 } 
    sub _build_attr2 { 1 } 
2

我已經在過去有這樣精確的要求了好幾次,今天我其實是有從元類,這意味着不允許有BUILD扭捏做。無論如何,我認爲這將是很好的分享,因爲它基本上不正是醚提到:

「這將允許標記屬性「,這是懶惰的,因爲它取決於 於其他屬性值要建,但我想它施工完成之前被捅 「」

然而,DERP DERP我不知道如何讓這樣一個在這裏CPAN模塊的一些代碼: https://gist.github.com/TiMBuS/5787018

把上面成Late.pm和那麼你可以使用我t像這樣:

package Thing; 
use Moose; 
use Late; 

has 'foo' => (
    is  => 'ro', 
    default => sub {print "setting foo to 10\n"; 10}, 
); 

has 'bar' => (
    is  => 'ro', 
    default => sub {print 'late bar being set to ', $_[0]->foo*2, "\n"; $_[0]->foo*2}, 
    late => 1, 
); 

#If you want.. 
__PACKAGE__->meta->make_immutable; 
1; 


package main; 

Thing->new(); 
#`bar` will be initialized to 20 right now, and always after `foo`. 
#You can even set `foo` to 'lazy' or 'late' and it will still work.