在OOP Perl中调用子例程
在浏览我接管的一些代码时,我遇到了以下几行:在OOP Perl中调用子例程,perl,oop,package,perl-module,Perl,Oop,Package,Perl Module,在浏览我接管的一些代码时,我遇到了以下几行: my @files = My::Module::DB::raw_info->search_like(customer_handle => $config->{client}, feed => $config->{site}, arrival =>"$date") 我知道这会从名为My::Module::DB::raw\u info的包中返回一个数组 我不确定(我只是在学习OOP)的是->search\u lik
my @files = My::Module::DB::raw_info->search_like(customer_handle => $config->{client}, feed => $config->{site}, arrival =>"$date")
我知道这会从名为My::Module::DB::raw\u info
的包中返回一个数组
我不确定(我只是在学习OOP)的是->search\u like
指的是什么
在My::Module::DB::raw_info
如有任何提示,将不胜感激。我才刚刚开始学这些东西。就像在火里洗澡一样。(我知道我以后会更快乐)哎呀 造成这个难题的可能原因是My::Module::DB扩展了其他一些类。沿着路线寻找一个街区
use parent Some::Module;
或
在My/Module/DB.pm的顶部附近
Edit:正如下面一些评论员所指出的,有许多方法可以对Perl类进行子类化,但这些方法可能是最常见的。(可能。)这可能是由于该方法是从基类继承的。然而,在非常奇怪的情况下,它也可以被动态地注入到模块的名称空间中,这是很难理解的 您可以通过蛮力搜索或找出模块的基类(可能更高的继承链)并只搜索基类代码来找到子模块。我将展示如何做到这两个方面:
暴力搜索:在复杂情况下,这可能是最简单的解决方案,因为子模块可能已被非祖先模块动态注入到模块的命名空间中,并且由于可以使用多种定义继承的方法,查找祖先模块并非100%容易(使用基础、使用父项、驼鹿材料、自动加载材料) 首先,找出使用My::Module加载的其他模块
perl -e 'use My::Module::DB::raw_info; print "$INC{$_}\n" foreach keys %INC'
这将打印所有这些模块的位置
然后,在所有代码中搜索子定义(以下应该都是一行,为了可读性,我将其拆分为两行):
如果返回的结果太多,请将grep更改为
grep "sub search_like"
`perl -e 'use My::Module::DB::raw_info; print "$INC{$_}\n" foreach keys %INC'`
这将在My::module::DB::raw_info继承的任何模块中找到定义,而不实际分析模块代码进行继承
继承: 使用
ISA
查找模块的父级,如下所示:
perl -e 'use My::Module::DB::raw_info; print "@My::Module::DB::raw_info::ISA\n";'
澄清一下,这只适用于“经典继承”模块使用的是
@ISA
,而不是Moose之类的东西。如果使用AutoLoader调用例程或将其动态注入到符号表中(可能发生在任何代码中,不一定发生在父代码中),则该方法也不起作用。该方法可以在My::Module::DB::raw_info
的超类中定义。请在调用search\u like
:
print @My::Module::DB::raw_info::ISA;
现在看看这些课程
如果这不起作用,可以使用的Dump()
查看子例程的来源:
use Devel::Peek;
Dump(\&search_like);
在输出中查找
GVGV::GV part
。也许这是某种继承的方法。阅读一些相关内容,在模块定义中搜索一些分配给@ISA
。在回答“我不确定的是什么,我只是在学习OOP(感谢我们的开发人员被解雇),->search\u like”指的是什么,search_like是raw_info类的一种方法,它将名称-值对作为其输入参数()
仅供参考,我发现另一本非常有用的书是。您可以使用core
Devel::Peek
模块查看子程序引用中保存的内部数据
要从OO方法获取子例程引用,可以使用所有对象的->can(…)
方法
my $code_ref = My::Module::DB::raw_info->can('search_like');
然后您可以打印出信息:
use Devel::Peek 'Dump';
Dump($code_ref);
根据Devel::Peek
的文档,您应该得到如下内容:
对子例程的引用如下所示:
SV = RV(0x798ec)
REFCNT = 1
FLAGS = (TEMP,ROK)
RV = 0x1d453c
SV = PVCV(0x1c768c)
REFCNT = 2
FLAGS = ()
IV = 0
NV = 0
COMP_STASH = 0x31068 "main"
START = 0xb20e0
ROOT = 0xbece0
XSUB = 0x0
XSUBANY = 0
GVGV::GV = 0x1d44e8 "MY" :: "top_targets"
FILE = "(eval 5)"
DEPTH = 0
PADLIST = 0x1c9338
这表明
- 子例程不是XSUB(因为START和ROOT不是零,XSUB是零)
- 它是在主程序包中编译的
- 名称为MY::top_targets
- 在程序的第五次评估中
- 当前未执行(参见深度)
- 它没有原型(原型字段缺失)
因此,COMP_STASH会向您显示代码的编译位置,而GVGV::GV会向您显示潜艇的全名。“extends”是一个驼鹿的东西。=)。如果您原谅这个双关语,驼鹿可能正在使用中答案更新为使用parent。(虽然base存在,并且已经存在了一段时间,所以您可能也会看到,但如果您看到它,请将其杀死,并改用parent。base充满了积垢)除了使用parent或extends之外,还有其他扩展类的方法。例如,使用base或direct@ISA change。首先:哇!我无法理解在这个问题上每个人都帮了我多大的忙。事实证明,代码是在扩展其他内容,特别是(当我提到它时,这一点将非常明显)Class::DBI。非常公开地感谢所有人,特别是威廉托特兰和DVK。你推动了一个新的方向,我从你的帖子中学到了一些东西。。。JW::如果A)它被导出器栓接B)它被驼鹿角色栓接C)在继承树的任何级别注入sub的任何其他内容,ISA都不会有帮助。@Kent-正确。这就是为什么我明确地说“它也可以动态地注入到模块的名称空间中,这很难理解。”并且作为第一种方法,提供了代码库的蛮力grep。为什么投反对票?我没有投反对票=)。当然,我没有看到=)。我记得有一种方法可以戳到一个单独的sub,看看它从哪里来,但它有点生疏。如果有什么安慰的话,我应该让自己有点沮丧,因为没有正确的RTFA-。。这应该做什么:
perl-e'使用我的::模块::DB::原始信息::ISA。“\n”;'代码>?::如果A)它被出口商栓住B)它被驼鹿栓住C)A
use Devel::Peek 'Dump';
Dump($code_ref);
SV = RV(0x798ec)
REFCNT = 1
FLAGS = (TEMP,ROK)
RV = 0x1d453c
SV = PVCV(0x1c768c)
REFCNT = 2
FLAGS = ()
IV = 0
NV = 0
COMP_STASH = 0x31068 "main"
START = 0xb20e0
ROOT = 0xbece0
XSUB = 0x0
XSUBANY = 0
GVGV::GV = 0x1d44e8 "MY" :: "top_targets"
FILE = "(eval 5)"
DEPTH = 0
PADLIST = 0x1c9338