2012-04-04 11 views
5

Tengo una situación donde tengo que encontrar la persona que llama de un paquete y el código se ve algo como:Perl Herencia - ¿Quién es la persona que llama de la clase padre

Inherited.pm:

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

BaseClass .PM

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

ahora tengo otra clase (MyClass.pm), que hace:
MyClass.pm:

$obj = Inherited->new(); 

Esto imprime Herencia. Pero necesito MyClass para ser la declaración impresa.

¿Podría alguien ayudarme en cómo resolver esto?

+0

No entiendo por qué esperas esto. 'Inherited' es la persona que llama. Puede marcar 'new()' de 'Inherited' y luego pasar esa información. – Cfreak

+0

@Cfreak: gracias por la respuesta. Ya acepto que pasar por el argumento es una solución, pero ¿hay alguna otra forma de encontrar al que llama de la clase padre? En mi situación real, necesito este tipo de funcionalidad sin pasar argumentos. – sundar

+0

Es posible que pueda utilizar la capacidad de seguimiento de pila de 'Carp' para buscar toda la lista de llamantes (' Carp :: longmess() '), pero no es una gran solución. Eche un vistazo a los módulos 'Class :: *' en CPAN. Puede haber una solución más elegante allí. – Cfreak

Respuesta

5

Cuando le da un argumento a caller, le dice cuántos niveles debe volver atrás. Le ha dado el argumento 0, que es el nivel actual. Si quieres un nivel superior, añadir 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; 
    } 

Ahora el resultado es:

0: Inherited 
1: MyClass 

siempre recuerde incluir programas de ejemplo completos en sus preguntas. El código de Perl que publicó estaba roto por varias otras razones no relacionadas con caller.

+0

Creo que el módulo Carp hace algo como esto: si la persona que llama está "relacionada" con la corvina, salta a la siguiente persona que llama. – Konerak

+0

gracias por su respuesta. Se entiende cómo funciona la persona que llama. – sundar

1

Si estoy leyendo su publicación correctamente, necesita encontrar el último marco en la pila de llamadas que está llamando a un constructor.

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); 
} 

El segundo fragmento de código va a manejar el caso cuando hay llamadas a funciones intermedias que no son constructores, por ejemplo, si la pila de llamadas se parece

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

la El primer fragmento devolvería la llamada para Inherited::new (que presumiblemente sería GrandChild, y el segundo devolvería la llamada de GrandChild::new.

+0

gracias por la respuesta. Su solución también me está funcionando, pero lamentablemente no puedo aceptar más de una respuesta aquí. – sundar

Cuestiones relacionadas