Wie funktioniert Zugriff auf ein Objekt die Symboltabelle für das aktuelle Paket?
-
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.
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!