2010-08-13 37 views
10

¿Es posible utilizar un objeto como una tecla hash?Objeto como clave hash

Por ejemplo, el siguiente código me permite usar una instancia de MyClass como una clave pero cuando iterar sobre las claves y el intento de invocar el método get_value, me sale el error:

no puede localizar método de objeto "Get_Value" a través de paquete "MiClase = HASH (0x12a4040)" (tal vez se olvidó de cargar "MiClase = 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; 
} 

Respuesta

14

Por defecto, todas las claves hash en Perl son cadenas, así que lo que está sucediendo en su código (que tiene otros problemas también), es que va a convertir el objeto en una cadena y el almacenamiento de la cadena.

En general, si desea utilizar un objeto como clave, la forma más sencilla de hacerlo es utilizar dos estructuras de datos, una que contenga sus objetos (una matriz) y otra que asigne los objetos a algunos valores (un hash). También es posible crear un hash vinculado que soporte objetos como claves, pero en general, los hashes atados van a ser más lentos que el simple uso de dos estructuras de datos.

El módulo estándar Tie::RefHash proporciona un mecanismo para usar objetos (y otras referencias) como teclas hash (que funcionan correctamente cuando las recupera).

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

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

Cualquier cosa es utilizado como stringified una clave hash. Por lo tanto, cuando utiliza su objeto como una clave hash, solo obtiene una representación de cadena de la misma y no el objeto real en sí.

La verdadera pregunta es, ¿por qué en el mundo le gustaría hacer esto?

Además, la sintaxis para asignar valores a un hash es $hash{key} = $val; la flecha se usa cuando se trata de una referencia hash.

Si desea asociar objetos con algún otro valor, una forma sería usar una matriz de hash, p. Ej.

my @foo; 
push @foo, { obj => MyClass->new(1), val => 0 }; 
push @foo, { obj => MyClass->new(2), val => 1 }; 

A continuación, puede llamar al $foo[0]{obj}->get_value();

Si sólo desea que los objetos sean capaces de volver algún identificador único por instancia, podría agregar un método que toma ventaja de Scalar :: de Util refaddr operador:

use Scalar::Util 'refaddr'; 

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

... 

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

Para más: perlobj, perldata, perlreftut, Scalar::Util

Cuestiones relacionadas