web-dev-qa-db-fra.com

Comment trouver le type d'objet que j'ai sur Perl?

Comment trouver le type d'objet avec lequel je traite en Perl? J'ai essayé d'utiliser Perl -d pour entrer dans le débogueur, mais je ne sais pas quoi faire. De même, j'aimerais avoir un moyen de voir facilement quelles méthodes sont disponibles pour chaque objet. Comment cela peut-il être fait?

29
John

Le moyen standard pour indiquer quel type d'objet vous avez est soit ref ou Scalar::Util::blessed. Si vous savez l'objet est béni, ils renverront la même information. 

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

Mais ref retournera également 'HASH' pour les hachages non bénis, alors que blessed refuse de jouer à ce jeu. 

En ce qui concerne la liste des méthodes, pour le style de pointeur béni de l'objet Perl, il est assez facile d'en coder une vous-même. Le code ci-dessous fonctionne assez bien pour moi. Elle retourne les noms des fonctions (celles prenant l'emplacement "CODE" du nom donné) mappées sur le paquet qui les définit. 

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;
}
  • Cela fonctionnera également pour des objets raisonnablement complexes, mais si le paquet propriétaire contient beaucoup de code généré, il ne sera pas très utile de savoir quel paquet les générateurs ont collé le pointeur de code. Cela signifiera davantage pour trouver quel paquet généré le code. 

  • Ceci étant le cas, vous pourriez obtenir le code lors de l'exécution de votre code, y compris Data::Dumper et définissez $Data::Dumper::Deparse sur 1, comme suit: (local $Data::Dumper::Deparse = 1;), puis basculez le pointeur de code comme suit: say Dumper( $code_ref );

  • Il WON'T fonctionne pour les méthodes valides qui n'ont pas encore été créées par une méthode AUTOLOAD. Si vous voyez ceux-ci dans la liste, l'objet peut en faire plus, mais vous ne savez pas tout ce qu'il fait.

  • La "classe de base" UNIVERSAL est incluse car cette classe contient un comportement utilisable par l'objet. 

Bonne chance.

28
Axeman

Le blessed function de Scalar :: Util vous indiquera le nom du paquet de toute référence bénie (un objet.)

Pour savoir quelles méthodes sont disponibles, consultez la documentation de ce paquet. Alternativement, vous pouvez utiliser quelque chose comme Class :: MOP :: Class pour instancier une métaclasse et obtenir des informations introspectives sur les méthodes qu'elle contient.

5
friedo

Juste pour compléter, voici une introduction très courte au débogueur.

Perl -d your_program

commence ça sous l'idiot. Vous aurez le contrôle à la première ligne de l’exécutable (les instructions d’utilisation et similaires ont déjà été exécutées à ce stade).

's' passera à la ligne suivante. Une fois que vous avez entré un 's', vous pouvez simplement appuyer sur retour pour le répéter. 's' va descendre dans les fonctions/sous-programmes/méthodes. Continuez à marcher jusqu’à votre retour ou entrez la commande 'r' pour exécuter le reste de la fonction et revenez juste après l’appel.

Si vous voulez passer en revue les sous-routines, c'est-à-dire les exécuter et les renvoyer sans avoir à intervenir et à les retourner, utilisez 'n. Le retour chariot après le premier "n" continue également à faire "n" pour vous.

Si vous connaissez la ligne sur laquelle vous souhaitez vous arrêter, utilisez la commande 'b' - b linumber - pour définir un point d'arrêt, puis sur 'c' pour continuer jusqu'à l'atteindre. Notez que chaque fois que vous revenez au point d'arrêt, vous vous arrêtez à nouveau. Utilisez 'B linumber' pour désactiver le point d'arrêt.

Supposons donc que vous êtes arrivé à quelque chose comme ceci:

my $obj = complex_function_returning_unknown_thing;

Le débogueur vient de vous montrer cette ligne, qui dit "Je ne l’ai pas encore exécutée, mais c’est ce que je ferai ensuite." Entrez 'n' pour exécuter le sous-programme, puis utilisez la commande 'x' pour examiner l'objet: 'x $ obj'. Si c'est gros, vous pouvez dire '| x $ obj' qui exécute la sortie via un pager. Pour voir les méthodes de l'objet, utilisez 'm $ obj'.

Le débogueur est bien plus compliqué, mais vous pouvez effectivement l'utiliser pour ce genre de choses - vous devez simplement voir le type d'objet que vous obtenez à partir d'un code et connaître les méthodes que cet objet a.

Il peut être plus utile de «x» l’objet, puis d’aller voir la source de la classe dans laquelle l’objet a été béni pour découvrir ce que vous devriez faire par opposition à ce que pouvez do. La commande 'x' est à peu près 'print print ($ obj)' croisée avec Data :: Dumper de toute façon.

3
Joe McMahon

Vous recherchez une réflexion en Perl. Je viens de googler "Perl Reflection" sans guillemets et cela a été soulevé:

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

Edit: _ Et ceci: http://markmail.org/message/i5mzik56ry4zoxxq

Edit: _ Et ceci: http://en.wikipedia.org/wiki/Reflection_(computer_science)#Perl

0
Hamish Grubijan