2010-10-27 15 views
7

Al mirar a través de un código que me hice cargo, me encontré con esta línea:Llamar a una subrutina en la programación orientada a objetos Perl

my @files = My::Module::DB::raw_info->search_like(customer_handle => $config->{client}, feed => $config->{site}, arrival =>"$date") 

sé que esto devuelve una matriz de un paquete llamado My::Module::DB::raw_info.

Lo que no estoy seguro (y recién estoy aprendiendo OOP), es a lo que se refiere ->search_like.

que no vieron eso como una variable o como una subrutina en My::Module::DB::raw_info

sería apreciada Alguna pista. Solo estoy empezando a aprender esto. Es como bañarse en fuego. (Sé que seré más feliz más tarde) ¡Ay!

Respuesta

5

La causa probable de su enigma es que My :: Module :: DB amplía alguna otra clase. Busque un bloque a lo largo de las líneas de

use parent Some::Module; 

o

BEGIN { extends Some::Module } 

cerca de la parte superior de mi/Módulo/DB.pm

Editar: Como algunos comentaristas están amablemente señalando a continuación , hay varias formas de subclasificar una clase Perl, pero estas son probablemente las más comunes. (Quizás)

+3

también "use base ..." – Arkadiy

+0

"extends" es una cosa de Moose. =). –

+0

no use base; _; , usa padre! –

8

Esto es probablemente debido al método heredado de una clase base. Sin embargo, en situaciones extremadamente extrañas, PODRÍA también ser inyectado dinámicamente en el espacio de nombre del módulo, lo que es mucho más difícil de entender.

Puede encontrar su sub o bien mediante la búsqueda de fuerza bruta o bien averiguando la clase base de un módulo (y posiblemente más arriba en la cadena de herencia) y buscando solo el código de las clases base. Voy a mostrar cómo hacer ambas cosas:


búsqueda de fuerza bruta: Este es probablemente la solución más fácil en casos complicados ya que el sub podría haber sido inyectado en el espacio del módulo dinámicamente por el módulo no ancestro y encontrar módulos ancestros no es 100% fácil debido a las múltiples formas de definir la herencia que podría haberse utilizado (use base, use parent, Moose stuff, cosas AUTOLOADED)

Primero, descubra qué otros módulos están cargados con My :: Módulo

perl -e 'use My::Module::DB::raw_info; print "$INC{$_}\n" foreach keys %INC' 

Esto imprimirá la ubicación de todos los módulos

Entonces, la búsqueda de la definición de sub en todo ese código (el siguiente debe ser una sola línea, que se dividió para facilitar su legibilidad en 2 líneas):

grep search_like 
    `perl -e 'use My::Module::DB::raw_info; print "$INC{$_}\n" foreach keys %INC'` 

Si esto devuelve demasiados resultados, cambie el grep para

grep "sub search_like" 
    `perl -e 'use My::Module::DB::raw_info; print "$INC{$_}\n" foreach keys %INC'` 

esto le encontrar la definición en cualquier módulo de Mi :: módulo :: DB :: raw_info hereda lado a otro m sin analizar el código del módulo para la herencia.


Herencia:

Descubre los padres del módulo usando ISA de la siguiente manera:

perl -e 'use My::Module::DB::raw_info; print "@My::Module::DB::raw_info::ISA\n";' 

Para aclarar, esto sólo funciona para módulos "heredadas clásicamente" usando @ISA, las cosas no alces . Tampoco funciona si se llama a la rutina mediante el Autocargador o se inyecta dinámicamente en la tabla de símbolos, lo que puede ocurrir en cualquier código, no necesariamente en el padre.

+0

:: ISA no ayudará si A) está atornillado por un exportador B) está atornillado por una función de Moose C) cualquier otra cosa que inyecte subs en cualquier nivel en el árbol de herencia. –

+0

@Kent - correcto. Por eso dije explícitamente que "PODRÍA también ser inyectado dinámicamente en el espacio de nombres del módulo, lo cual es mucho más difícil de descifrar", y ofrecí, como primer método, la grep de fuerza bruta del código base. ¿Por qué downvote? – DVK

+0

No downvote de mí =). Aunque, concedido, no vi eso =). Recuerdo que había una manera de meterme en un submarino individual para ver de dónde venía, pero está un poco oxidado. –

1

El método se puede definir en las superclases de My::Module::DB::raw_info. Inserte esta línea antes de la llamada a search_like:

print @My::Module::DB::raw_info::ISA; 

Ahora mira en estas clases.

Si esto no funciona, puede utilizar Devel::Peek 's Dump() para ver donde el vino de subrutina:

use Devel::Peek; 
Dump(\&search_like); 

Busque GVGV::GV part en la salida.

+1

:: ISA no ayudará si A) está atornillado por un exportador B) está atornillado por un rol de Moose C) cualquier otra cosa que inyecte subs en cualquier nivel en el árbol de herencia –

+1

& search_like puede no funcionar como piensas, probablemente necesites 'Dump (My :: Module :: DB -> can ('raw_info')) '(suponiendo, por supuesto, raw_info no es (horrores) AUTOLOAD y hecho incorrectamente) –

1

Quizás es algún método heredado. Lea un poco acerca de Perl inheritance, busque alguna asignación a @ISA en su definición de módulo.

+1

:: ISA solo es útil si es la herencia lo que hace que exista.La subinyección en tiempo de compilación (familia del exportador, roles, etc.) no será visible. –

1

Respondiendo a "De lo que no estoy seguro, y recién estoy aprendiendo OOP (gracias a que nuestro desarrollador es despedido), es a lo que se refiere" -> search_like ", search_like es un método del clase raw_info que toma pares de valores de nombre como sus parámetros de entrada (Perl Cookbook section 10.7).

FYI, el otro libro que me parece muy útil es Programming Perl.

+0

Acabo de descifrar el Perl Cookbook abierto y le agradezco que ofrezca esto ..... JW –

2

Puede usar el módulo Devel::Peek para ver los datos internos guardados en las referencias de subrutinas.

Para obtener una referencia de subrutina a partir de un método OO, utiliza el método ->can(...) de todos los objetos.

my $code_ref = My::Module::DB::raw_info->can('search_like'); 

y luego se puede imprimir la información:

use Devel::Peek 'Dump'; 

Dump($code_ref); 

De acuerdo a Devel::Peek 's docs, usted debe obtener algo como esto:

Una referencia a una subrutina se parece a esto :

SV = RV(0x798ec) 
     REFCNT = 1 
     FLAGS = (TEMP,ROK) 
     RV = 0x1d453c 
    SV = PVCV(0x1c768c) 
     REFCNT = 2 
     FLAGS =() 
     IV = 0 
     NV = 0 
     COMP_STASH = 0x31068 "main" 
     START = 0xb20e0 
     ROOT = 0xbece0 
     XSUB = 0x0 
     XSUBANY = 0 
     GVGV::GV = 0x1d44e8 "MY" :: "top_targets" 
     FILE = "(eval 5)" 
     DEPTH = 0 
     PADLIST = 0x1c9338 

Esto muestra que

  • la subrutina no es un XSUB (ya que START y ROOT no son cero, y XSUB es cero);
  • que se compiló en el paquete principal;
  • con el nombre MY :: top_targets;
  • dentro de una 5ta evaluación en el programa;
  • no está actualmente ejecutado (ver PROFUNDIDAD);
  • no tiene prototipo (campo PROTOTIPO falta).

Entonces, COMP_STASH le muestra dónde se compiló el código, y GVGV :: GV le muestra el nombre completo del sub.

Cuestiones relacionadas