我理解使用builder
可以使子类轻松地覆盖属性默认值,角色可以轻松地覆盖它们。这也可以使用default
实现,如下所示:
has 'foo' =>
is => 'rw',
isa => 'Str',
default => sub { $_[0]->_build_foo };
我想知道使用builder
是否还有更多的优势,我不知道?我自己想出了一些:
builder
是声明性的,所以您可以内省_build_foo
builder
构建的foo
,消除了一个子程序包装器,使它稍微有点fasterbuilder
允许使用有用的lazy_build
.。
更新以澄清,这不是关于default
与builder
的一般问题,而是default => sub { $_[0]->_build_foo }
与builder => '_build_foo'
之间的关系。
发布于 2012-03-01 18:54:11
我想你已经回答了你自己的问题。使用builder
允许后期绑定,这与要被子类化的角色和类很好地配合。如果构建器很长的话,它也是很有价值的--我在属性定义中的default
长度从来不超过一行。没有真正的功能差异;default
可以很容易地模仿builder
,但是结果不太好。
发布于 2012-03-01 18:18:47
两者之间没有区别
default => sub { $_[0]->_build_foo }
和
builder => '_build_foo'
default
和builder
的主要区别在于,一个调用anon,另一个调用命名方法。
has created_time_stamp => (
default => sub { time() },
);
对比
has created_time_stamp => (
builder => '_build_created_time_stamp',
);
sub _build_created_time_stamp { time() }
使用default
可以减少代码的滚动,因为一切都是您需要它的地方。我就是为了这个原因才用它的。也就是说,使用较少的打字是一个额外的好处。
它还迫使您更明确地说明如何覆盖构建器。其他答案认为这是一个骗局,但我认为,在一个尚未被构造的对象上调用虚拟方法是一个糟糕的实践!这就是BUILD
的作用。
发布于 2012-03-01 20:13:46
适当地使用“生成器”和“默认”可以使您的代码更易于阅读和组织。
“‘builder”还可以适应一种熟悉的编程模式,在这种模式中,私有方法以下划线开头。
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)
}
此外,使用构建器可以将昂贵的函数转换为回忆录访问器,而无需触及原始方法:
sub get_things {
my $self = shift;
return +{ map { $_ => $self->price_for($_) }
$self->wodgets->calulate_expensive_things };
用回忆录重构:
has things => ( is => 'ro', lazy => 1, builder => 'get_things' );
这些都是我使用构建器来澄清代码的大多数方法。
https://stackoverflow.com/questions/9526347
复制相似问题