2010-08-13 67 views
10

是否可以將對象用作散列鍵?作爲散列鍵的對象

例如,下面的代碼允許我使用MyClass的實例作爲重點,但是當我遍歷鍵,並試圖調用get_value方法,我得到的錯誤:

無法找到對象的方法 「的get_value」 通過包 「MyClass的= HASH(0x12a4040)」(也許你忘了裝載 「MyClass的= HASH(0x12a4040)」?)

package MyClass; 
use strict; 

sub new 
{ 
    my $class = shift; 
    my $self = { 
     _value => shift 
    }; 
    bless $self, $class; 
    return $self; 
} 

sub get_value { 
    my($self) = @_; 
    return $self->{_value}; 
} 

my %hash =(); 
%hash->{new MyClass(1)} = 0; 
%hash->{new MyClass(2)} = 1; 

for my $key (keys %hash) 
{ 
    print $key->get_value; 
} 

回答

14

默認情況下,在Perl中所有的哈希鍵是字符串,那麼什麼是你的代碼發生(它有其他的問題),是你的對象轉換爲字符串,並存儲該字符串。

一般來說,如果你想使用一個對象作爲關鍵字,最簡單的方法是使用兩個數據結構,一個持有對象(一個數組),另一個將對象映射到某些值(哈希)。也可以創建一個將支持對象作爲關鍵字的綁定哈希,但總的來說,綁定哈希將比簡單地使用兩個數據結構慢。

標準模塊Tie::RefHash提供了一種使用對象(和其他引用)作爲散列鍵(當你得到它們時正常工作)的機制。

use Tie::RefHash; 
tie my %hash, 'Tie::RefHash'; 

$hash{MyClass->new(1)} = 0; # never use the indirect object syntax 
.... 
6

任何作爲哈希密鑰字符串化使用。所以,當你的對象用作散列鍵時,你只能得到它的字符串表示而不是實際的對象本身。

真正的問題是,爲什麼在這個世界上你想要這樣做?

此外,將值分配給散列的語法爲$hash{key} = $val;在處理散列引用時使用箭頭。

如果您想將對象與其他值關聯起來,一種方法是使用散列數組,例如,

my @foo; 
push @foo, { obj => MyClass->new(1), val => 0 }; 
push @foo, { obj => MyClass->new(2), val => 1 }; 

然後你可以撥打$foo[0]{obj}->get_value();

如果你只是想你的對象能夠返回一些獨特的每個實例ID,可以添加一個需要標量的優勢的方法::的Util的refaddr操作:

use Scalar::Util 'refaddr'; 

sub unique_id { 
    my $self = shift; 
    return refaddr $self; 
} 

... 

$hash{MyClass->new(1)->unique_id} = 0; 

更多:perlobjperldataperlreftutScalar::Util