2010-01-19 18 views
28

¿Cómo puedo encontrar el tipo de objeto al que me refiero en Perl? Intenté usar perl -d para ingresar al depurador, pero no estoy seguro de qué hacer entonces. Del mismo modo, me gustaría una forma de ver fácilmente qué métodos están disponibles para cada objeto, ¿cómo se puede hacer eso?¿Cómo encontrar el tipo de objeto que tengo en Perl?

+2

Relacionado: http://stackoverflow.com/questions/460676/how-do-i-determine-if-an-object-implements-a-method-in-perl –

+0

Estaba intentando depurar una secuencia de comandos iterando a través de una gran variedad de objetos, muchas veces con Perl encuentro que no sé qué métodos están disponibles para cada objeto, así que estaba buscando una manera fácil de descubrirlo. – John

Respuesta

27

La forma estándar de indicar qué tipo de objeto tiene es ref o Scalar::Util::blessed. Si sabe el objeto está bendecido, entonces devuelve la misma información.

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

Pero ref también volverá 'HASH' para hashes sin bendecir, mientras blessed se niega a jugar ese juego.

En cuanto a una lista de métodos, para el bendito estilo de puntero del objeto perl, es bastante fácil codificar uno usted mismo. El siguiente código funciona bastante bien para mí. Devuelve los nombres de las funciones (los que toman el "espacio del CÓDIGO" del nombre de pila) asignados al paquete que los define.

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; 
} 
  • Esto funciona para objetos bastante complejos, así, pero si el paquete propietaria contiene una gran cantidad de código generado, que no va a ser tan útil saber qué paquete de los generadores atrapados el puntero del código en Va a significar más para encontrar qué paquete generó el código.

  • Siendo este el caso, podría obtener el código de funcionamiento de su código, incluyendo Data::Dumper y el establecimiento de $Data::Dumper::Deparse a 1, de este modo: (local $Data::Dumper::Deparse = 1;) y luego volcar el puntero del código, así: say Dumper($code_ref);

  • Es NO funcionará para métodos válidos que aún no se han creado por ningún método AUTOLOAD. Si ves los que están en la lista, el objeto puede hacer más, pero todo lo que hace, no lo sabes.

  • Se incluye la "clase base" UNIVERSAL, porque esa clase contiene un comportamiento utilizable por el objeto.

Buena suerte.

5

La función de blessedScalar::Util le dirá el nombre del paquete de cualquier referencia bendita (un objeto).

para averiguar qué métodos están disponibles, consulte la documentación de dicho paquete. Alternativamente, puede usar algo como Class::MOP::Class para instanciar una metaclase y obtener información introspectiva sobre los métodos que contiene.

3

Para completar, aquí hay una breve introducción al depurador.

perl -d your_program 

comienza bajo el insecto. Obtendrá el control en la primera línea ejecutable (las instrucciones de uso y similares ya se han ejecutado en este punto).

's pasará a la siguiente línea. Una vez que haya ingresado una 's', simplemente puede presionar regresar para repetirla. 's' pasará a funciones/subrutinas/métodos. O siga caminando hasta que regrese o ingrese el comando 'r' para ejecutar el resto de la función y regresar a la derecha después de la llamada.

Si desea pasar por encima de las subrutinas, es decir, ejecutarlas y regresar sin tener que entrar y regresar, use 'n. El retorno del carro después de la primera 'n' también sigue haciéndolo 'n'.

Si conoce la línea donde desea detenerse, use el comando 'b' - b linenumber - para establecer un punto de interrupción, luego 'c' para continuar hasta que llegue a ella. Tenga en cuenta que cada vez que 'c' y vuelve al punto de interrupción se detendrá nuevamente. Use 'B linenumber' para desactivar el punto de interrupción.

Así que vamos a asumir que ha llegado a algo como esto:

my $obj = complex_function_returning_unknown_thing; 

El depurador sólo le ha mostrado esta línea, que dice: "No he ejecutado todavía, pero es lo que voy a hacer a continuación. " Ingrese 'n' para ejecutar la subrutina, luego use el comando 'x' para ver el objeto: 'x $ obj'. Si es grande, puede decir '| x $ obj', que ejecuta la salida a través de un buscapersonas. Para ver qué métodos tiene el objeto, use 'm $ obj'.

Hay mucho más para el depurador, pero de hecho puede usarlo para este tipo de cosas; simplemente necesita ver el tipo de objeto que está recibiendo de algún código y averiguar qué métodos tiene el objeto que obtuvo tiene.

Puede ser más útil a 'x' el objeto y, a continuación, ir a buscar a la fuente de la clase del objeto ha sido bendecido en averiguar lo que debe hacer a diferencia de lo que puede hacer. El comando 'x' es más o menos 'print ref ($ obj)' cruzado con Data :: Dumper de todos modos.

Cuestiones relacionadas