对象作为哈希键

时间:2010-08-13 18:24:59

标签: perl hash

是否可以将对象用作哈希键?

例如,下面的代码允许我使用MyClass的实例作为键,但是当我遍历键并尝试调用get_value方法时,我收到错误:

无法通过包“MyClass = HASH(0x12a4040)”找到对象方法“get_value”(也许你忘了加载“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;
}

2 个答案:

答案 0 :(得分:16)

默认情况下,Perl中的所有哈希键都是字符串,所以代码中发生了什么(也有其他问题),就是将对象转换为字符串并存储字符串。

通常,如果要将对象用作键,最简单的方法是使用两个数据结构,一个用于保存对象(一个数组),另一个用于将对象映射到某些值(哈希)。也可以创建一个将对象作为键支持的绑定哈希,但一般来说,绑定哈希比简单地使用两个数据结构要慢。

标准模块Tie::RefHash提供了一种机制,可以将对象(和其他引用)用作哈希键(当你将它们取回时可以正常工作)。

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

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

答案 1 :(得分:8)

用作散列键的任何内容都是字符串化的。因此,当您将对象用作哈希键时,您只获得它的字符串表示而不是实际的对象本身。

真正的问题是,为什么世界上你想要这样做?

此外,为哈希值分配值的语法是$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,您可以添加一个利用Scalar :: Util的refaddr运算符的方法:

use Scalar::Util 'refaddr';

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

...

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

更多信息:perlobjperldataperlreftutScalar::Util