2010-08-13 14 views
10

È possibile utilizzare un oggetto come chiave hash?Oggetto come tasto cancelletto

Ad esempio, il seguente codice mi permette di utilizzare un'istanza di MyClass come chiave, ma quando ho scandire le chiavi e tentare di richiamare il metodo get_value, ottengo l'errore:

non può individuare metodo di un oggetto "Get_Value" tramite pacchetto "MyClass = cancelletto (0x12a4040)" (forse si è dimenticato di caricare "MyClass = cancelletto (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; 
} 

risposta

14

per impostazione predefinita, tutte le chiavi di hash in Perl sono stringhe, quindi quello che succede in voi il codice (che ha altri problemi), è che si sta convertendo l'oggetto in una stringa e memorizzare la stringa.

In generale, se si desidera utilizzare un oggetto come chiave, il modo più semplice per farlo consiste nell'utilizzare due strutture dati, una che contiene gli oggetti (una matrice) e un'altra che associa gli oggetti ad alcuni valori (un hash). È anche possibile creare un hash legato che supporterà gli oggetti come chiavi, ma in generale gli hash legati saranno più lenti del semplice utilizzo di due strutture dati.

Il modulo standard Tie::RefHash fornisce un meccanismo per l'utilizzo di oggetti (e altri riferimenti) come chiavi hash (che funzionano correttamente quando vengono restituiti).

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

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

Tutto utilizzato come una chiave hash è stringata. Pertanto, quando si utilizza l'oggetto come chiave hash, si ottiene solo una rappresentazione di stringa e non l'oggetto stesso.

La vera domanda è: perché nel mondo vorresti farlo?

Inoltre, la sintassi per l'assegnazione di valori a un hash è $hash{key} = $val; la freccia è usata quando hai a che fare con un riferimento all'hash.

Se si desidera associare oggetti con qualche altro valore, un modo sarebbe utilizzare una matrice di hash, ad es.

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

Poi si potrebbe chiamare $foo[0]{obj}->get_value();

se si desidera solo gli oggetti per essere in grado di restituire un po 'di ID univoco per-esempio, si potrebbe aggiungere un metodo che sfrutta Scalar :: di Util refaddr dell'operatore:

use Scalar::Util 'refaddr'; 

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

... 

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

Per maggiori: perlobj, perldata, perlreftut, Scalar::Util

Problemi correlati