Dan*_*ski 5 oop perl introspection moose
我经常在我的工作地点处理一个庞大的,没有很好记录的,面向对象的Perl回购.在维护代码的同时,我经常需要跟踪从其他类继承的内容,以便我能够理解他们正在做什么.例如,我需要弄清楚$self->mystery它在做什么以及它在做什么:
package Foo::Bar;
use Moose;
use Method::Signatures;
use Foo::Bar::Element;
use Foo::Bar::Function;
use base qw (Baz::Foo::Bar);
method do_stuff ($some_arg) {
# mystery is not defined in Foo::Bar
my $mystery = $self->mystery;
$mystery->another_mystery($some_arg);
}
Run Code Online (Sandbox Code Playgroud)
我经常发现自己花费太多时间来追踪父类.所以我的问题是,有一个简单的方法让我弄清楚$self->mystery从哪里来的?或者换句话说,我需要找到声明神秘的地方.
通过"简单的方式",我并不是指使用ack或grep通过文件串搜索.我希望有一些我可以安装和使用的调试模块,这可以帮助我一些见解.
谢谢.
comes_from方法!你不需要下载任何特殊的工具或模块,更不用说一些巨大的IDE,因为你的未记录的类结构已经变得太复杂,只有人类才能理解而没有笨重的IDE.
为什么不?简单:标准Perl包含您 获得所需答案所需的一切.找出问题所在的简单方法是使用非常有用的comes_from方法:
$origin = $self->comes_from("mystery");
$secret_origin = $self->comes_from("another_mystery");
$birthplace = Some::Class->comes_from("method_name");
Run Code Online (Sandbox Code Playgroud)
这将返回该方法将解析的子例程的原始名称.如你所见,comes_from作为对象方法和类方法,就像can和isa.
请注意,当我说出它解析为的子例程的名称时,我指的是最初创建子例程的位置,在任何导入或继承之前.例如,这段代码:
use v5.10.1;
use Path::Router;
my($what, $method) = qw(Path::Router dump);
say "$what->$method is really ", $what->comes_from($method);
Run Code Online (Sandbox Code Playgroud)
打印出来:
Path::Router->dump is really Moose::Object::dump
Run Code Online (Sandbox Code Playgroud)
类似的电话也会发现:
Net::SMTP->mail is really Net::SMTP::mail
Net::SMTP->status is really Net::Cmd::status
Net::SMTP->error is really IO::Handle::error
Run Code Online (Sandbox Code Playgroud)
它也适用于普通的ole子程序:
SQL::Translator::Parser::Storable->normalize_name
is really SQL::Translator::Utils::normalize_name
Run Code Online (Sandbox Code Playgroud)
虽然它不需要标准Perl以外的任何东西,但可爱的comes_from方法并不完全内置.为了使您和您的所有类和对象可以访问它,只需在某处添加这些代码 - 您真正喜欢的任何地方:)
sub UNIVERSAL::comes_from($$) {
require B;
my($invocant, $invoke) = @_;
my $coderef = $invocant->can($invoke) || return;
my $cv = B::svref_2object($coderef);
return unless $cv->isa("B::CV");
my $gv = $cv->GV;
return if $gv->isa("B::SPECIAL");
my $subname = $gv->NAME;
my $packname = $gv->STASH->NAME;
return $packname . "::" . $subname;
}
Run Code Online (Sandbox Code Playgroud)
通过声明,作为一个UNIVERSAL子,现在大家谁的人得到发挥它,就像他们做can和isa.请享用!