2012-04-04 2 views
5

Ho una situazione in cui ho bisogno di trovare il chiamante di un pacchetto e il mio codice simile a:Perl Inheritance - Chi è il chiamante della classe genitore

Inherited.pm:

package Inherited; 
our @ISA = qw(BaseClass); 
sub new { 
    SUPER::new(); 
} 

BaseClass .pm

package BaseClass; 
sub new { 
    $a = caller(0); 
    print $a 
} 

Ora ho un'altra classe (MyClass.pm) che fa:
MyClass.pm:

$obj = Inherited->new(); 

Questa stampa è ereditata. Ma ho bisogno di MyClass per essere la dichiarazione stampata.

Qualcuno potrebbe aiutarmi per risolvere questo problema?

+0

Non capisco perché te lo aspetti. "Inherited" è il chiamante. Puoi controllare il 'new()' di 'Inherited' e poi passare quell'informazione. – Cfreak

+0

@Cfreak: grazie per la risposta. Ya accetto che passare per argomento sia una soluzione, ma esiste un altro modo per trovare il chiamante della classe genitore. Nel mio scenario attuale ho bisogno di questo tipo di funzionalità senza passare argomenti. – sundar

+0

Potresti essere in grado di usare la capacità di stack trace di "Carp" per cercare l'intera lista di chiamanti ('Carp :: longmess()') ma non è una grande soluzione. Dai un'occhiata ai moduli 'Class :: *' su CPAN. Potrebbe esserci una soluzione più elegante lì. – Cfreak

risposta

5

Quando si dà un argomento a caller, si indica quanti livelli si desidera tornare indietro. Hai dato l'argomento 0, che è il livello corrente. Se si desidera un livello superiore, aggiungere 1:

use v5.12; 

package Inherited { 
    our @ISA = qw(BaseClass); 
    sub new { 
     $_[0]->SUPER::new(); 
    } 
} 

package BaseClass { 
    sub new { 
     say "0: ", scalar caller(0); 
     say "1: ", scalar caller(1); 
    } 
} 

package MyClass { 
    my $obj = Inherited->new; 
    } 

Ora il risultato è:

0: Inherited 
1: MyClass 

ricordarsi di includere sempre programmi completi esempio nella tua domande. Il codice Perl che hai postato è stato rotto per vari altri motivi non correlati a caller.

+0

Penso che il modulo Carp faccia qualcosa del genere: se il chiamante è "collegato" al cretino, salta invece al prossimo chiamante. – Konerak

+0

grazie per la vostra risposta. Ha capito come funziona il chiamante. – sundar

1

Se sto leggendo il tuo messaggio correttamente, devi trovare l'ultimo frame nello stack di chiamate che sta chiamando un costruttore.

package BaseClass; 
sub new { 
    my $a = caller(0); 
    for (my $n=0; my @c=caller($n); $n++) { 
     last if $c[4] !~ /::new$/; 
     $a = $c[0]; 
    } 
    print $a; 
} 

o

package BaseClass; 
sub new { 
    my @a; 
    unshift @a, [ caller(@a) ] while caller(@a); 
    my ($a) = grep { $_->[4] =~ /::new$/ } @a; 
    print $a // caller(0); 
} 

Il secondo frammento di codice si gestisce il caso quando ci sono chiamate di funzione intermedi che non sono costruttori, ad esempio, se la pila chiamata assomiglia

GrandChild::new 
GrandChild::init 
Inherited::new 
BaseClass::new 

la il primo snippet restituirebbe il chiamante per Inherited::new (che presumibilmente sarebbe GrandChild e il secondo restituirà il chiamante di GrandChild::new.

+0

grazie per la risposta. La tua soluzione funziona anche per me, ma purtroppo non posso accettare più di una risposta qui. – sundar