考虑到Perl中的包名,如何从包中调用子例程?
给定一个包含表示包名称的字符串的变量,如何调用包的特定子例程?
这是我发现的最接近的事情: package MyPackage; sub echo { print shift; } my $package_name = 'MyPackage'; $package_name->echo('Hello World'); 1; 这段代码的问题是子程序被称为类方法;包名称作为第一个参数传入.我想从包名称调用子例程,而不会隐式传入特殊的第一个参数. 解决方法
Perl方法调用只是常规子例程,它将invocant作为第一个值.
use strict; use warnings; use 5.10.1; { package MyPackage; sub new{ bless {},shift } # overly simplistic constructor (DO NOT REUSE) sub echo{ say @_ } } my $package_name = 'MyPackage'; $package_name->echo; my $object = $package_name->new(); $object->echo; # effectively the same as MyPackage::echo($object) MyPackage MyPackage=HASH(0x1e2a070) 如果要在没有调用者的情况下调用子例程,则需要以不同方式调用它. { no strict 'refs'; ${$package_name.'::'}{echo}->('Hello World'); &{$package_name.'::echo'}('Hello World'); } # only works for packages without :: in the name $::{$package_name.'::'}{echo}->('Hello World'); $package_name->can('echo')->('Hello World'); > my $code_ref = $package_name->can('echo'); $code_ref->('Hello World'); 使用 >可以被包或它继承的任何类重写. 这实际上可能是您正在寻找的行为. { no strict 'refs'; &{ $package_name.'::echo' }('Hello World'); } 通常不建议使用符号引用.部分问题在于,如果您不打算使用符号引用,则可能会意外地使用符号引用.这就是为什么你不能使用严格的“参考”;有效. 这可能是做你想做的最简单的方法. $MyPackage::{echo}->('Hello World'); $::{'MyPackage::'}{echo}->('Hello World'); $main::{'MyPackage::'}{echo}->('Hello World'); $main::{'main::'}{'MyPackage::'}{echo}->('Hello World'); $main::{'main::'}{'main::'}{'main::'}{'MyPackage::'}{echo}->('Hello World'); 唯一的问题是你必须拆分$package_name :: *Some::Long::Package::Name::echo = &;MyPackage::echo; $::{'Some::'}{'Long::'}{'Package::'}{'Name::'}{echo}('Hello World'); sub get_package_stash{ my $package = shift.'::'; my @package = split /(?<=::)/,$package; my $stash = %:: ; $stash = $stash->{$_} for @package; return $stash; } get_package_stash('Some::Long::Package::Name')->{echo}('Hello World'); 这不是一个大问题.快速查看CPAN后,您会找到Package::Stash. use Package::Stash; my $stash = Package::Stash->new($package_name); my $coderef = $stash->get_symbol('&echo'); $coderef->('Hello World'); (Pure Perl版Package::Stash使用符号引用,而不是Stash) 甚至可以创建子例程/方法的别名,就好像是从使用Exporter的模块导入的: *echo = &;{$package_name.'::echo'}; echo('Hello World'); 我建议限制别名的范围: { local *echo = &;{$package_name.'::echo'}; echo('Hello World'); } 这是一个例外,您可以使用带有严格“refs”的符号引用. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |