代码之家  ›  专栏  ›  技术社区  ›  Trevor

对象作为哈希键

  •  11
  • Trevor  · 技术社区  · 14 年前

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

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

    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 回复  |  直到 14 年前
        1
  •  16
  •   Eric Strom    14 年前

    默认情况下,Perl中的所有散列键都是字符串,因此代码中发生的事情(还有其他问题)是将对象转换为字符串并存储字符串。

    标准模块 Tie::RefHash

    use Tie::RefHash;
    tie my %hash, 'Tie::RefHash';
    
    $hash{MyClass->new(1)} = 0;  # never use the indirect object syntax
    ....
    
        2
  •  8
  •   friedo    14 年前

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

    真正的问题是,你到底为什么要这么做?

    $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;
    

    perlobj , perldata perlreftut , Scalar::Util