In che modo un oggetto accede alla tabella dei simboli per il pacchetto corrente?

StackOverflow https://stackoverflow.com/questions/1822312

  •  10-07-2019
  •  | 
  •  

Domanda

Come posso accedere alla tabella dei simboli per il pacchetto corrente in cui è stato istanziato un oggetto? Ad esempio, ho qualcosa del genere:

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;

Se nell'implementazione di do_your_job utilizzo __PACKAGE__ , cercherà nel pacchetto MyModule . Come potrei farlo sembrare nel pacchetto giusto?

EDIT: proverò a chiarire questo aspetto. Supponiamo che io abbia il seguente codice:

package MyMod;

sub new {
    return bless {},

Come posso accedere alla tabella dei simboli per il pacchetto corrente in cui è stato istanziato un oggetto? Ad esempio, ho qualcosa del genere:

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;

Se nell'implementazione di do_your_job utilizzo __PACKAGE__ , cercherà nel pacchetto MyModule . Come potrei farlo sembrare nel pacchetto giusto?

EDIT: proverò a chiarire questo aspetto. Supponiamo che io abbia il seguente codice:

<*>

Ora, $ x dovrebbe in qualche modo notare che main è il pacchetto corrente e cerca nella sua tabella dei simboli. Ho provato a usare il benedetto Scalar :: Util , ma mi ha comunque dato MyModule invece di main . Spero che ora sia un po 'più chiaro.

[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;

Ora, $ x dovrebbe in qualche modo notare che main è il pacchetto corrente e cerca nella sua tabella dei simboli. Ho provato a usare il benedetto Scalar :: Util , ma mi ha comunque dato MyModule invece di main . Spero che ora sia un po 'più chiaro.

È stato utile?

Soluzione

Vuoi solo chiamante

chiamante ti dice il pacchetto da cui è stato chiamato. (Qui ho aggiunto un po 'di standard perl.)

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;

Per cercarlo e vedere se è definito e poi cercarlo per chiamarlo, lo duplicherebbe come standard perl non fa l'eliminazione della sottoespressione comune, quindi potresti anche 1) recuperarlo e 2) verificare la definizione di lo slot e 3) eseguirlo se è definito.

Ora se crei un oggetto in un pacchetto e lo usi in un altro, non sarà di grande aiuto. Probabilmente dovrai aggiungere un campo aggiuntivo come 'owning_package' nel costruttore.

package MyMod;

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

Ora $ x- > {owning_package} conterrà 'main' .

Altri suggerimenti

Vedi perldoc -f caller :

#!/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;

Output:

C:\Temp> h
No, you can't!
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top