2010-08-13 78 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