是否可以将对象用作哈希键?
例如,下面的代码允许我使用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;
}
答案 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;