2010-08-13 12 views
10

Kann ein Objekt als Hash-Schlüssel verwendet werden?Objekt als Hash-Schlüssel

Zum Beispiel der folgende Code ermöglicht es mir, eine Instanz von MyClass als Schlüssel zu verwenden, aber wenn ich die Schlüssel überlaufen und versuchen, die get_value Methode aufzurufen, erhalte ich die Fehlermeldung:

kann nicht gefunden werden Objektmethode "get_value" über-Paket "MyClass = hash (0x12a4040)" (vielleicht vergessen Sie "MyClass = hash (0x12a4040)"? zu laden) als Hash-Schlüssel wird verwendet, Zeichenfolge

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

Antwort

14

Standardmäßig werden alle Hash-Schlüssel in Perl sind Strings, so was in Ihnen Code geschieht (was auch noch andere Probleme hat), ist das Objekt in einen String und Speichern der Zeichenfolge konvertieren. Wenn Sie ein Objekt als Schlüssel verwenden möchten, besteht die einfachste Möglichkeit darin, zwei Datenstrukturen zu verwenden, eine, die Ihre Objekte enthält (ein Array), und eine andere, die die Objekte auf einige Werte abbildet (ein Hash). Es ist auch möglich, einen gebundenen Hash zu erzeugen, der Objekte als Schlüssel unterstützt, aber im Allgemeinen werden gebundene Hashes langsamer sein als einfach zwei Datenstrukturen zu verwenden.

Das Standardmodul Tie::RefHash bietet einen Mechanismus zum Verwenden von Objekten (und anderen Referenzen) als Hash-Schlüssel (die ordnungsgemäß funktionieren, wenn Sie sie zurückerhalten).

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

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

Alles. Wenn Sie also Ihr Objekt als Hash-Schlüssel verwenden, erhalten Sie nur eine String-Repräsentation und nicht das eigentliche Objekt.

Die eigentliche Frage ist, warum in der Welt möchten Sie dies tun?

Auch die Syntax für die Zuweisung von Werten zu einem Hash ist $hash{key} = $val; Der Pfeil wird verwendet, wenn Sie mit einer Hash-Referenz arbeiten.

Wenn Sie Objekte mit einem anderen Wert verknüpfen möchten, wäre ein Weg, ein Array von Hashes zu verwenden, z.

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

Dann könnten Sie anrufen $foo[0]{obj}->get_value();

Wenn Sie nur wollen, um Ihre Objekte einige einzigartige pro-Instanz-ID in der Lage zurückzukehren, könnten Sie eine Methode hinzufügen, die die Vorteile der Scalar nimmt :: Util des refaddr Betreiber:

use Scalar::Util 'refaddr'; 

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

... 

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

Weitere: perlobj, perldata, perlreftut, Scalar::Util