Wie funktioniert Zugriff auf ein Objekt die Symboltabelle für das aktuelle Paket?

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

  •  10-07-2019
  •  | 
  •  

Frage

Wie kann ich die Symboltabelle für das aktuelle Paket zugreifen ein Objekt in instanziiert wurde? Zum Beispiel habe ich so etwas wie folgt aus:

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;

Wenn bei der Umsetzung von do_your_job I __PACKAGE__ verwenden, wird es in dem MyModule Paket suchen. Wie kann ich es in dem richtigen Paket aussehen?

EDIT: Ich werde versuchen, diese klarer zu machen. Angenommen, ich habe den folgenden Code:

package MyMod;

sub new {
    return bless {},$_[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;

Jetzt sollten $x bemerken irgendwie, dass main das aktuelle Paket ist, und suchen sie Symboltabelle ist. Ich habe versucht, Scalar::Util die gesegnet mit, aber es gab mir noch statt MyModule main. Hoffentlich ist dies ein bisschen jetzt klarer.

War es hilfreich?

Lösung

Sie wollen einfach nur caller

caller sagt Ihnen, das Paket, von dem es hieß. (Hier habe ich einige 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;

Um es zu sehen und sehen, ob es definiert ist und es dann rufen Sie die es als Standard Perl duplizieren würde nicht Gemeinsame Subexpression Beseitigung tun, so dass Sie könnte genauso gut 1) abrufen es, und 2) überprüfen Definiert von der Schlitz, und 3) ausgeführt, wenn es sie definiert ist.

Nun, wenn Sie ein Objekt in einem Paket zu erstellen und es in einem anderen verwenden, das wird nicht zu viel Hilfe sein. Sie würden wahrscheinlich ein zusätzliches Feld wie 'owning_package' im Konstruktor hinzufügen müssen.

package MyMod;

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

Jetzt wird $x->{owning_package} 'main' enthalten.

Andere Tipps

Siehe perldoc -f Anrufer :

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

Ausgabe:

C:\Temp> h
No, you can't!
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top