it-swarm.dev

Wie finde ich heraus, welchen Objekttyp ich in Perl habe?

Wie kann ich in Perl herausfinden, mit welchem ​​Objekttyp ich es zu tun habe? Ich habe versucht, mit Perl -d den Debugger aufzurufen, bin mir aber nicht sicher, was ich dann tun soll. Ebenso möchte ich einen Weg finden, um einfach zu sehen, welche Methoden für jedes Objekt verfügbar sind. Wie kann das gemacht werden?

29
John

Die Standardmethode für die Angabe des Objekttyps ist entweder ref oder Scalar::Util::blessed. Wenn Sie wissen das Objekt gesegnet ist, geben sie dieselbe Information zurück. 

my $class1 = blessed( $obj );
my $class2 = ref $obj;

ref gibt jedoch auch 'HASH' für nicht gesegnete Hashes zurück, während blessed dieses Spiel ablehnt. 

Für eine Liste von Methoden ist es für den gesegneten Zeigerstil eines Perl-Objekts einfach, eine davon selbst zu codieren. Der folgende Code funktioniert ziemlich gut für mich. Es gibt die Namen der Funktionen (diejenigen, die den "CODE-Slot" des angegebenen Namens annehmen) zurück, die dem Paket zugeordnet sind, das sie definiert. 

sub class_methods { 
    use Class::ISA;
    my $obj = shift;
    return unless ref( $obj );
    my %meth_names;
    foreach my $anc ( Class::ISA::self_and_super_path( ref $obj ), 'UNIVERSAL' ) {
        my $stash = \%{"$anc\::"};
        my @funcs 
            = grep { m/^[_\p{Alpha}]/                # begins with _ or alpha
                   && !exists $meth_names{$_}        # no clobbering
                   &&  defined *{$stash->{$_}}{CODE} # has a filled CODE slot
                   } keys %$stash
            ;
        # assign to the "hash slice", keyed by all the entries in @funcs
        # the value of $anc repeated as many times as elements in @funcs.
        @meth_names{@funcs} = ( $anc ) x @funcs;
    }
    return %meth_names;
}
  • Dies funktioniert auch für relativ komplexe Objekte, aber wenn das besitzende Paket eine Menge generierten Codes enthält, ist es nicht besonders hilfreich zu wissen, in welchem ​​Paket die Generatoren den Code-Pointer stecken. Es wird mehr bedeuten, welches Paket zu finden ist generiert den Code. 

  • Ist dies der Fall, erhalten Sie might den Code aus der Ausführung Ihres Codes, einschließlich Data::Dumper und Setzen von $Data::Dumper::Deparse auf 1 wie folgt: (local $Data::Dumper::Deparse = 1;) und dann den Code-Zeiger wie folgt: say Dumper( $code_ref );

  • Es WON'T funktioniert für gültige Methoden, die noch mit einer beliebigen AUTOLOAD-Methode erstellt werden müssen. Wenn Sie diese in der Liste sehen, macht das Objekt möglicherweise mehr, aber was es alles tut, wissen Sie nicht.

  • Die "Basisklasse" UNIVERSAL ist enthalten, da diese Klasse Verhalten enthält, das vom Objekt verwendet werden kann. 

Viel Glück.

28
Axeman

Die blessed - Funktion von Scalar :: Util teilt Ihnen den Paketnamen einer gesegneten Referenz (ein Objekt) mit.

Informationen zu den verfügbaren Methoden finden Sie in der Dokumentation zu diesem Paket. Alternativ können Sie etwas wie Class :: MOP :: Class verwenden, um eine Metaklasse zu instanziieren und introspektive Informationen über die darin enthaltenen Methoden zu erhalten.

5
friedo

Der Vollständigkeit halber sei hier kurz auf den Debugger eingegangen.

Perl -d your_program

beginnt es unter dem Trottel. Sie erhalten die Kontrolle in der ersten ausführbaren Zeile (Use-Anweisungen und Ähnliches wurden an dieser Stelle bereits ausgeführt).

's' springt zur nächsten Zeile. Sobald Sie ein "s" eingegeben haben, können Sie einfach die Eingabetaste drücken, um es zu wiederholen. 's' springt in Funktionen/Unterprogramme/Methoden zurück. Gehen Sie entweder so lange weiter, bis Sie zurückkehren, oder geben Sie den Befehl 'r' ein, um den Rest der Funktion auszuführen und nach dem Aufruf direkt wieder zurückzukehren.

Wenn Sie Unterroutinen überspringen möchten, das heißt, sie ausführen und zurückkehren, ohne einspringen zu müssen, verwenden Sie 'n. Der Wagenrücklauf nach dem ersten 'n' macht auch 'n' für Sie.

Wenn Sie die Linie kennen, an der Sie anhalten möchten, legen Sie mit dem Befehl 'b' - b Nummer - einen Haltepunkt fest, und fahren Sie mit 'c' fort, bis Sie ihn erreichen. Beachten Sie, dass Sie jedes Mal, wenn Sie "c" und zum Haltepunkt zurückkehren, wieder anhalten. Verwenden Sie 'B-Leinenummer', um den Haltepunkt wieder auszuschalten.

Nehmen wir also an, Sie haben so etwas erreicht:

my $obj = complex_function_returning_unknown_thing;

Der Debugger hat Ihnen gerade diese Zeile angezeigt, die besagt "Ich habe dies noch nicht ausgeführt, aber es ist das, was ich als Nächstes tun werde." Geben Sie 'n' ein, um die Subroutine auszuführen, und verwenden Sie dann den Befehl 'x', um das Objekt anzuzeigen: 'x $ obj'. Wenn es groß ist, können Sie '| x $ obj' sagen, das die Ausgabe über einen Pager ausführt. Verwenden Sie 'm $ obj', um zu sehen, welche Methoden das Objekt hat.

Der Debugger hat noch viel mehr zu bieten, aber Sie können ihn tatsächlich für diese Art von Dingen verwenden. Sie müssen einfach den Typ eines Objekts sehen, das Sie aus einem Code erhalten, und herausfinden, welche Methoden das Objekt hat, das Sie haben.

Es kann sinnvoller sein, das Objekt zu "x", und dann die Quelle der Klasse zu betrachten, in die das Objekt gesegnet wurde, um herauszufinden, was Sie sollten im Gegensatz zu dem tun, was Sie Can tun. Der 'x'-Befehl ist so ziemlich' print ref ($ obj) ', gekreuzt mit Data :: Dumper.

3
Joe McMahon

Sie suchen nach Reflexion in Perl. Ich habe gerade "Perl Reflection" ohne Zitate gegoogelt und das kam auf:

http://coding.derkeiler.com/Archive/Perl/perl.beginners/2004-10/0291.html

Bearbeiten: Und dies: http://markmail.org/message/i5mzik56ry4zoxxq

Bearbeiten: Und dies: http://en.wikipedia.org/wiki/Reflection_(computer_science)#Perl

0
Hamish Grubijan