2008-08-14 19 views
18

In Perl ist ein Objekt nur ein Verweis auf einen der grundlegenden Perl-Datentypen, der in eine bestimmte Klasse gesegnet wurde. Wenn Sie die Funktion ref() für einen nicht geblendeten Verweis verwenden, wird Ihnen mitgeteilt, auf welchen Datentyp der Verweis verweist. Wenn Sie jedoch ref() für eine gesegnete Referenz aufrufen, wird der Name des Pakets zurückgegeben, in das die Referenz eingefügt wurde.Wie kann ich den Typ einer gesegneten Referenz in Perl bestimmen?

Ich möchte den tatsächlichen zugrunde liegenden Typ der gesegneten Referenz kennen. Wie kann ich das feststellen?

Antwort

18

Scalar::Util::reftype() ist die sauberste Lösung. Das Modul Scalar::Util wurde dem Perl-Kern in Version 5.7 hinzugefügt, ist aber für ältere Versionen (5.004 oder höher) von CPAN verfügbar.

Sie können auch die Sonde mit UNIVERSAL::isa():

$x->isa('HASH')    # if $x is known to be an object 
UNIVERSAL::isa($x, 'HASH') # if $x might not be an object or reference 

Offensichtlich würden Sie haben auch für ARRAY und SCALAR Typen zu überprüfen. Das Modul UNIVERSAL (das als Basisklasse für alle Objekte dient) ist seit Perl 5.003 Teil des Kerns.

Eine andere Möglichkeit - einfach, aber ein wenig schmutzig - ist die Referenz zu string. Unter der Annahme, dass die Klasse stringification nicht überlastet werden Sie so etwas wie Class=HASH(0x1234ABCD) zurück, die Sie analysieren können den zugrunde liegenden Datentyp zu extrahieren:

my $type = ($object =~ /=(.+)\(0x[0-9a-f]+\)$/i); 
+3

Sie wollen nur eval {$ x-> isa ($ type)}; Wenn das kein Objekt ist, bekommst du falsch zurück. Wenn es nicht der richtige Typ ist, werden Sie falsch, und wenn es der richtige Typ ist, werden Sie wahr. :) –

2

Und mein erster Gedanke war: "Objekte in Perl sind immer Hash-Refs, also was zum Hack?"

Aber Scalar :: Util :: reftype ist die Antwort. Danke, dass Sie die Frage hier gestellt haben.

Hier ist ein Code-Schnipsel, um dies zu beweisen .. (falls es irgendjemanden von Nutzen ist).

 
$> perl -e 'use strict; use warnings "all"; my $x = [1]; bless ($x, "ABC::Def"); use Data::Dumper; print Dumper $x; print ref($x) . "\n"; use Scalar::Util "reftype"; print reftype($x) . "\n"'` 

Ausgang:

 
$VAR1 = bless([ 
       1 
       ], 'ABC::Def'); 
ABC::Def 
ARRAY 
+3

Objekte werden oft als Hashreferenzen implementiert, aber es ist keine Voraussetzung. Ein Objekt kann ein beliebiger Referenztyp sein. –

6

Sie sollten wahrscheinlich nicht tun. Der zugrunde liegende Typ eines Objekts ist ein Implementierungsdetail, mit dem Sie sich nicht anlegen sollten. Warum willst du das wissen?

+0

Einverstanden, und ich wusste, dass jemand diesen Kommentar abgeben würde. Ich brauchte das wirklich nur, während ich versuchte, eine Struktur herauszufinden, die ein Modul erzeugte, damit ich das Modul ändern konnte. Ich wollte einen bestimmten Schlüssel aus beliebigen Hashes in der Struktur löschen, da sie ein rohes JPEG enthielten. –

+2

Später entdeckte ich, dass ich Data :: Dumper :: sortkeys verwenden konnte, um diese Daten zu filtern, damit Data :: Dumper keine Megabyte binärer Ausgabe produzierte. –