7

在查看我接管的一些代码时,我遇到了这一行:

 my @files = My::Module::DB::raw_info->search_like(customer_handle => $config->{client}, feed => $config->{site}, arrival =>"$date")

我知道这会从名为My::Module::DB::raw_info.

我不确定(我只是在学习 OOP)是->search_like指什么。

我没有将其视为变量或子程序My::Module::DB::raw_info

任何提示将不胜感激。我才刚刚开始学习这些东西。这就像沐浴在火中。(我知道我以后会更快乐)哎呀!

4

6 回答 6

8

这可能是由于从基类继承的方法。然而,在极其奇怪的情况下,它也可以动态地注入到模块的命名空间中,这很难弄清楚。

您可以通过蛮力搜索或通过找出模块的基类(可能是继承链的更高层)并仅搜索基类代码来找到您的子。我将展示如何做到这两点:


蛮力搜索:这可能是复杂情况下最简单的解决方案,因为子可能已经被非祖先模块动态注入到模块的命名空间中,并且由于定义继承的多种方法可能已经找到祖先模块并不是 100% 容易使用过(使用基础,使用父级,驼鹿的东西,自动加载的东西)

首先,找出哪些其他模块加载了 My::Module

perl -e 'use My::Module::DB::raw_info; print "$INC{$_}\n" foreach keys %INC'

这将打印所有这些模块的位置

然后,在所有该代码中搜索子定义(以下应该都是一行,为了便于阅读,我将其拆分为 2 行):

grep search_like 
   `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 调用例程或动态注入符号表(这可能发生在任何代码中,不一定在父代码中),它也不起作用。

于 2010-10-27T15:00:34.853 回答
5

您的难题的可能原因是 My::Module::DB 扩展了其他一些类。寻找沿线的块

use parent Some::Module;

或者

BEGIN { extends Some::Module }

靠近 My/Module/DB.pm 的顶部

编辑:正如一些评论者在下面有用地指出的那样,有许多方法可以子类化 Perl 类,但这些可能是最常见的。(也许。)

于 2010-10-27T14:53:42.797 回答
2

您可以使用核心Devel::Peek模块查看子例程引用中保存的内部数据。

要从 OO 方法获取子例程引用,请使用->can(...)所有对象的方法。

my $code_ref = My::Module::DB::raw_info->can('search_like');

然后你可以打印出信息:

use Devel::Peek 'Dump';

Dump($code_ref);

根据Devel::Peek's docs,你应该得到这样的东西:

对子例程的引用如下所示:

    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 为名;
  • 在程序的第 5 个 eval 内;
  • 它当前未执行(参见 DEPTH);
  • 它没有原型(缺少原型字段)。

因此,COMP_STASH 显示代码的编译位置,而 GVGV::GV 显示子程序的全名。

于 2010-10-27T19:31:01.920 回答
1

该方法可以在 的超类中定义My::Module::DB::raw_info。在调用之前插入这一行search_like

print @My::Module::DB::raw_info::ISA;

现在看看这些类。

如果这不起作用,您可以使用Devel::PeekDump()查看子例程的来源:

use Devel::Peek;
Dump(\&search_like);

GVGV::GV part在输出中寻找。

于 2010-10-27T15:01:25.063 回答
1

也许这是一些继承的方法。阅读一些关于Perl 继承@ISA的内容,在你的模块定义中搜索一些赋值。

于 2010-10-27T15:03:54.570 回答
1

为了回答“我不确定,我只是在学习 OOP(感谢我们的开发人员被解雇),就是“->search_like”所指的内容。”,search_like 是 raw_info 类的一个方法,它采用名称值对作为其输入参数(Perl Cookbook 第 10.7 节)。

仅供参考,我觉得非常有用的另一本书是Programming Perl

于 2010-10-27T16:23:42.407 回答