Объект как ключ хеша

Действительно ли возможно использовать объект в качестве ключа хеша?

Например, следующий код позволяет мне использовать экземпляр 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;
}
12
задан Trevor 13 August 2010 в 18:24
поделиться

2 ответа

По умолчанию все хеш-ключи в Perl являются строками, поэтому то, что происходит в вашем коде (у которого также есть другие проблемы), заключается в том, что вы конвертируете объект в строку и сохраняете строку .

В общем, если вы хотите использовать объект в качестве ключа, самый простой способ сделать это - использовать две структуры данных, одна из которых содержит ваши объекты (массив), а другая сопоставляет объекты с некоторыми значениями ( хеш). Также возможно создать связанный хеш, который будет поддерживать объекты в качестве ключей, но в целом связанные хэши будут медленнее, чем простое использование двух структур данных.

Стандартный модуль Tie :: RefHash предоставляет механизм для использования объектов (и других ссылок) в качестве хэш-ключей (которые работают правильно, когда вы их получаете обратно).

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

$hash{MyClass->new(1)} = 0;  # never use the indirect object syntax
....
16
ответ дан 2 December 2019 в 06:25
поделиться

Все, что используется в качестве хеш-ключа, преобразуется в строку. Поэтому, используя свой объект в качестве хеш-ключа, вы получаете только его строковое представление, а не сам объект.

Настоящий вопрос в том, зачем вам это нужно?

Кроме того, синтаксис для присвоения значений хешу следующий: $ 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 () ;

Если вы просто хотите, чтобы ваши объекты могли возвращать уникальный идентификатор для каждого экземпляра, вы можете добавьте метод, который использует преимущества оператора 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

8
ответ дан 2 December 2019 в 06:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: