Pregunta

¿Cómo podría acceder a la tabla de símbolos para el paquete actual en el que se creó una instancia de un objeto? Por ejemplo, tengo algo como esto:

my $object = MyModule->new;
# this looks in the current package, to see if there's a function named run_me
# I'd like to know how to do this without passing a sub reference
$object->do_your_job;

Si en la implementación de do_your_job uso __PACKAGE__ , buscará en el paquete MyModule . ¿Cómo podría hacer que se vea en el paquete correcto?

EDITAR: intentaré aclarar esto. Supongamos que tengo el siguiente código:

package MyMod;

sub new {
    return bless {},

¿Cómo podría acceder a la tabla de símbolos para el paquete actual en el que se creó una instancia de un objeto? Por ejemplo, tengo algo como esto:

my $object = MyModule->new;
# this looks in the current package, to see if there's a function named run_me
# I'd like to know how to do this without passing a sub reference
$object->do_your_job;

Si en la implementación de do_your_job uso __PACKAGE__ , buscará en el paquete MyModule . ¿Cómo podría hacer que se vea en el paquete correcto?

EDITAR: intentaré aclarar esto. Supongamos que tengo el siguiente código:

<*>

Ahora, $ x debería notar de alguna manera que main es el paquete actual, y busca en su tabla de símbolos. Intenté usar Scalar :: Util 's bendito, pero todavía me dio MyModule en lugar de main . Con suerte, esto es un poco más claro ahora.

[0] } sub do_your_job { my $self = shift; # of course find_package_of is fictional here # just for this example's sake, $pkg should be main my $pkg = find_package_of($self); if(defined &{ $pkg . '::run_me' }) { # the function exists, call it. } } package main; sub run_me { print "x should run me.\n"; } my $x = MyMod->new; # this should find the run_me sub in the current package and invoke it. $x->do_your_job;

Ahora, $ x debería notar de alguna manera que main es el paquete actual, y busca en su tabla de símbolos. Intenté usar Scalar :: Util 's bendito, pero todavía me dio MyModule en lugar de main . Con suerte, esto es un poco más claro ahora.

¿Fue útil?

Solución

Solo desea llamador

llamador le dice el paquete desde el que se llamó. (Aquí agregué algunos perl estándar).

use Symbol qw<qualify_to_ref>;
#...
my $pkg = caller;

my $symb   = qualify_to_ref( 'run_me', $pkg );
my $run_me = *{$symb}{CODE};
$run_me->() if defined $run_me;

Para buscarlo y ver si está definido y luego buscarlo para llamarlo, lo duplicaría ya que perl estándar no elimina la subexpresión común, por lo que también podría 1) recuperarlo y 2) verificar la definición de la ranura, y 3) ejecutarlo si está definido.

Ahora, si crea un objeto en un paquete y lo usa en otro, eso no será de mucha ayuda. Probablemente necesite agregar un campo adicional como 'owning_package' en el constructor.

package MyMod;

#...
sub new { 
    #...
    $self->{owning_package} = caller || 'main';
    #...
}

Ahora $ x- > {owning_package} contendrá 'main' .

Otros consejos

Ver perldoc -f llamador :

#!/usr/bin/perl

package A;
use strict; use warnings;

sub do_your_job {
    my ($self) = @_;
    my ($pkg) = caller;
    if ( my $sub = $pkg->can('run_me') ) {
        $sub->();
    }
}

package B;
use strict; use warnings;

sub test {
    A->do_your_job;
}

sub run_me {
    print "No, you can't!\n";
}

package main;

use strict; use warnings;

B->test;

Salida:

C:\Temp> h
No, you can't!
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top