2014-02-06 53 views
1

中調用方法我有一類設置屬性如下:如何建設者

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讀寫,我可能會在數據寫入訪問,調用該方法然後從訪問返回值駝鹿寫回存取。
  • 如果我把它變成一個普通的舊方法,那麼我必須定義另一個屬性,比如_raw_data,將數據存儲在那裏,修改refresh()以使用該屬性,其他所有使用_data()
  • 破壞封裝和直接訪問底層$self->{_data}

我試過after '_load' => \&refresh;,但那只是創建了一個無限循環。

回答

1

這將是一個不錯的使用觸發器:

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

除觸發器不上缺省的/內置值工作 - 只傳遞給構造明確,或傳遞給一個作家/存取方法值。悲傷的臉。 :-(

一個解決辦法是重新編寫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 
}