2011-02-05 37 views
2

如果我有一個簡單的綁定標類,每遞增它讀我是這樣做的時候:構造綁定標

package Counter; 

use strict; 
use warnings; 

sub TIESCALAR { 
    my $class = shift; 
    my $value = 0; 

    bless \$value, $class; 

    return \$value; 
} 

sub FETCH { 
    my $self = shift; 

    my $value = $$self; 

    $$self++; 

    return $value; 
} 

sub STORE { 
    my $self = shift; 
    $$self = shift; 
} 

1; 

但是創建一個計數器變量我必須使用tie。我可以創建一個計數器並將其導出。但是我真正想要做的是讓它看起來OO。看來,我可以創造一個new方法是這樣的:

sub new { 
    my $class = shift; 
    my $counter; 

    tie $counter, $class; 

    return $counter; 
} 

然後在我的主腳本做得到兩個計數器:

my $counter1 = Counter->new(); 
my $counter2 = Counter->new(); 

我假定這不起作用,因爲領帶沒有按」沒有一個副本存在(我在某個地方的文檔中閱讀過),難道沒有辦法做到這一點?

注意:我知道這只是一個風格問題,但看起來更正確。

回答

11

綁定魔法不是通過賦值進行的,因爲它適用於變量本身,而不是它包含的值。您有幾種選擇:

返回一個參考:

sub new {tie my $ret, ...; \$ret} 

my $counter = Counter->new; 

say $$counter; 

分配到水珠:

our ($counter); 

*counter = Counter->new; # same new as above 

say $counter; 

或者你可以將變量傳遞到構造函數:

sub new {my $class = shift; tie $_[0], $class} 

Counter->new(my $counter); 

say $counter; 

你甚至可以使用這兩種方法構造一個構造函數:

sub new { 
    my $class = shift; 
    tie $_[0] => $class; 
    \$_[0] 
} 

our $glob; *glob = Counter->new; 

Counter->new(my $lexical); 

在最後兩個例子中,tie直接傳遞給$_[0]。原因是@_的元素是參數列表的別名,所以它的工作原理與您在tie行中鍵入了my $counter一樣。


最後,當你的例子是非常明確的,並遵循最佳做法,TIMTOWTDI的精神,你可以寫你的整個類是這樣的:

{package Counter; 
    sub TIESCALAR {bless [0]} 
    sub FETCH {$_[0][0]++} 
    sub STORE {$_[0][0] = $_[1]} 
    sub new {tie $_[1] => $_[0]; \$_[1]} 
} 

最後一件事提到。雖然你的問題是關於綁定變量,你也可以用重載來實現這一目標:

{package Counter; 
    use overload fallback => 1, '""' => sub {$_[0][0]++}; 
    sub new {bless [0]} 
} 

my $counter = Counter->new; # overloading survives the assignment 

say $counter; 

但你失去了通過轉讓的計數器復位的能力。您可以在Counter上添加sub set {$_[0][0] = $_[1]}方法。

+0

感謝您的奇妙完整答案! – 2011-02-05 12:59:02