我在Moose对象中有一堆懒惰的功能。
有些建筑商需要一些时间才能完成。
我想nvoke所有构建器(转储“bomplete”对象)。 我可以一次性构建所有延迟功能,还是必须手动调用每个功能以使其运行?
答案 0 :(得分:6)
如果你想在构建器中使用“lazy”属性,但确保在new
返回之前构造它们的值,通常要做的是在BUILD
中调用访问器。
sub BUILD {
my ($self) = @_;
$self->foo;
$self->bar;
}
足以完成工作,但最好添加一条评论,并将这些显然无用的代码解释给不懂成语的人。
答案 1 :(得分:3)
也许您可以使用元类来获取“懒惰”属性的列表。例如:
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 :(得分:2)
过去我曾多次提出这个要求,今天我实际上必须从元类中做到这一点,这意味着不允许进行BUILD调整。无论如何,我觉得分享会很好,因为它基本上完全与以下提到的一致:
'它会允许标记属性“这是懒惰的,因为它取决于 关于要构建的其他属性值,但我希望它被戳 施工结束前。“'
然而,derp derp我不知道如何制作CPAN模块,所以这里有一些代码: https://gist.github.com/TiMBuS/5787018
将上述内容放入Late.pm然后你可以这样使用它:
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.