2010-10-27 13 views
7

Quando si guarda attraverso un codice ho assunto la direzione, mi sono imbattuto in questa linea:Chiamare una subroutine in OOP Perl

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

So che questo restituisce un array da un pacchetto chiamato My::Module::DB::raw_info.

Quello che non sono sicuro di (e sto solo imparando OOP), è quello che si riferisce a ->search_like.

non ho visto che come una variabile o come subroutine in My::Module::DB::raw_info

Eventuali suggerimenti sarebbero apprezzati. Sto solo iniziando a imparare questa roba. È come fare il bagno nel fuoco. (So ​​che sarò più felice dopo) Yikes!

risposta

5

La causa più probabile del vostro enigma è che la mia :: Modulo :: DB estende qualche altra classe. Cercare un blocco lungo le linee di

use parent Some::Module; 

o

BEGIN { extends Some::Module } 

vicino alla parte superiore del mio/modulo/DB.pm

Edit: Come alcuni commentatori sono utilmente sottolineando seguito , ci sono diversi modi per sottoclasse una classe Perl, ma questi sono probabilmente i più comuni. (Forse.)

+3

anche "usa base ..." – Arkadiy

+0

"extends" è una cosa Moose. =). –

+0

non utilizzare la base; _; , usa genitore! –

8

Ciò è probabilmente dovuto al metodo di essere ereditato da una classe base. Tuttavia, nelle situazioni estremamente strane, potrebbe anche essere iniettato dinamicamente nello spazio dei nomi del modulo, che è molto più difficile da capire.

È possibile trovare il proprio sub con la ricerca della forza bruta o calcolando la classe base di un modulo (e possibilmente più in alto nella catena di ereditarietà) e cercando solo il codice delle classi di base. Vi mostrerò come fare entrambe le cose:


ricerca forza bruta: Questa è probabilmente la soluzione più semplice in casi complicati in quanto il sub avrebbe potuto essere iniettato nel namespace del modulo in modo dinamico dal modulo non antenato e trovare i moduli degli antenati non è facile al 100% a causa di molteplici modi di definire l'ereditarietà che potrebbe essere stata utilizzata (utilizzare base, utilizzare padre, roba Moose, materiale AUTOLOADED)

Innanzitutto, scoprire quali altri moduli sono caricati con My :: Modulo

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

Ciò stamperà la posizione di tutti quei moduli

Poi, ricerca per la definizione sub in tutto ciò che il codice (il seguente dovrebbe essere tutto una riga, ho diviso in su per migliorare la leggibilità in 2 linee):

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

Se questo restituisce troppi risultati, modificare il grep per

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

questo vi troverà la definizione in qualsiasi modulo :: modulo :: DB :: raw_info eredita fro m senza analizzare effettivamente il codice del modulo per ereditarietà.


Ereditarietà:

Scopri padre del modulo utilizzando ISA come segue:

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

Per chiarire, questo funziona solo per i moduli "classico ereditato" utilizzando @ISA, roba non Moose . Inoltre, non funziona se la routine viene chiamata utilizzando AutoLoader o viene iniettata dinamicamente nella tabella dei simboli, il che può avvenire in qualsiasi codice, non necessariamente in quello principale.

+0

:: ISA non aiuterà se A) è imbullonato da un esportatore B) imbullonato da un ruolo Moose C) qualsiasi altra cosa che inietta sottotitoli a qualsiasi livello nell'albero ereditario. –

+0

@Kent - corretto. Questo è il motivo per cui ho detto esplicitamente "potrebbe anche essere iniettato dinamicamente nello spazio dei nomi del modulo che è molto più difficile da capire" e offerto - come primo metodo - la forza bruta di codice base. Perché il downvote? – DVK

+0

No downvote da me =). Sebbene, concesso, non l'ho visto =). Ricordo che c'era un modo per colpire un singolo sub per vedere da dove proveniva, ma è un po 'arrugginito. –

1

Il metodo può essere definito nelle superclassi di My::Module::DB::raw_info. Inserire questa riga prima della chiamata a search_like:

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

Ora guardate in queste classi.

Se questo non funziona, è possibile utilizzare Devel::Peek s' Dump() per vedere dove la subroutine è venuto da:

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

Cercare GVGV::GV part nell'output.

+1

:: ISA non aiuterà se A) è imbullonato da un esportatore B) imbullonato da un ruolo Moose C) qualsiasi altra cosa che inietta sottotitoli a qualsiasi livello nell'albero ereditario –

+1

e search_like potrebbero non funzionare come credi, probabilmente avrai bisogno di 'Dump (My :: Module :: DB -> can ('raw_info')) '(supponendo che raw_info non sia (horrors) AUTOLOAD e sia fatto in modo errato) –

1

Forse è un metodo ereditato. Leggi un po 'su Perl inheritance, cerca qualche incarico a @ISA nella definizione del tuo modulo.

+1

:: ISA è utile solo se è l'intrinseca causa della sua esistenza.Sotto-iniezione in fase di compilazione (famiglia di esportatori, ruoli, ecc.) Non sarà visibile. –

1

In risposta a "Ciò di cui non sono sicuro e sto imparando OOP (grazie al licenziamento del nostro sviluppatore), è ciò a cui si riferisce" -> search_like ". Search_like è un metodo del classe raw_info che accetta coppie nome valore come parametri di input (Perl Cookbook section 10.7).

FYI, l'altro libro che trovo molto utile è Programming Perl.

+0

Ho appena aperto il ricettario Perl e apprezzo che tu stia offrendo questo ..... JW –

2

È possibile utilizzare il modulo nucleo Devel::Peek per esaminare i dati interni contenuti nei riferimenti di subroutine.

Per ottenere un riferimento di subroutine da un metodo OO, si utilizza il metodo ->can(...) di tutti gli oggetti.

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

e quindi è possibile stampare le informazioni:

use Devel::Peek 'Dump'; 

Dump($code_ref); 

Secondo Devel::Peek 's docs, si dovrebbe ottenere qualcosa di simile:

Un riferimento a una subroutine assomiglia a questo :

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 

Ciò indica che

  • la subroutine non è un XSUB (poiché START e ROOT non sono zero e XSUB è zero);
  • che è stato compilato nel pacchetto principale;
  • con il nome MY :: top_targets;
  • all'interno di un quinto eval nel programma;
  • non è attualmente eseguito (vedi DEPTH);
  • non ha un prototipo (manca il campo PROTOTYPE).

Quindi, COMP_STASH mostra dove è stato compilato il codice e GVGV :: GV mostra il nome completo del sottotitolo.

Problemi correlati