如何在构建器中调用方法

时间:2014-02-06 05:27:27

标签: perl attributes builder moose

我有一个类,其属性设置如下:

has _data => (
    is => 'ro',
    lazy => 1,
    builder => '_load',
);

sub _load {
    my $self = shift;
    return retrieve $self->_file;
}

但是我现在想要在返回数据之前调用已经在类上定义的方法。

在老派Perl OO,我会做这样的事情:

sub _load {
    # Assuming laziness is implemented somewhere else.
    my $self = shift;
    $self->{_data} = retrieve $self->_file;
    $self->refresh;  # which does something with $self->{_data}
    return $self->{_data};
}

但是我无法想象在穆斯这样做的“干净”方式。

我考虑过以下情况,但认为它们非常难看,并且必须有更好的方法来做到这一点。

  • 如果我进行_data读写,我可能会将数据写入访问者,调用该方法然后从Moose的访问者返回值以写回访问者。
  • 如果我把它变成一个普通的老方法,那么我必须定义另一个属性,比如_raw_data,将数据存储在那里,修改refresh()以使用该属性,其他一切都使用_data()
  • 违反封装并直接访问基础$self->{_data}

我尝试了after '_load' => \&refresh;,但这只是创造了一个无限循环。

1 个答案:

答案 0 :(得分:1)

这可以很好地利用触发器:

has _data => (
   is      => 'ro',
   lazy    => 1,
   builder => '_load',
   trigger => sub { shift->refresh },
);

除了触发器对默认值/构建值不起作用 - 仅对显式传递给构造函数的值或传递给writer / accessor方法。悲伤的脸。 : - (

一种解决方案是重写您的refresh方法,这样它就可以接受一个参数(如果没有给出参数,可能会回退到$self->_data上运行,而不是在$self->_data上运行

sub _load {
   my $self = shift;
   my $tmp = retrieve $self->_file;
   $self->refresh($tmp);
   return $tmp;
}

sub refresh {
   my $self = shift;
   my $data = scalar(@_) ? $_[0] : $self->_data;
   # do something with $data
}