在 OOP Perl 中调用子例程

发布于 2024-09-29 13:37:02 字数 454 浏览 5 评论 0原文

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

 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 中的变量或子例程

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

When looking through some code I took over, I came across this line:

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

I know that this returns an array from a package called My::Module::DB::raw_info.

What I'm not sure of (and I am just learning OOP), is what ->search_like refers to.

I didn't see that as a variable or as a subroutine in My::Module::DB::raw_info

Any hints would be appreciated. I'm only beginning to learn this stuff. It's like bathing in fire. (I know I'll be happier later though) Yikes!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

满天都是小星星 2024-10-06 13:37:02

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

您可以通过强力搜索或找出模块的基类(可能是继承链的更高层)并仅搜索基类代码来找到您的子项目。我将展示如何同时执行这两项操作:


强力搜索:在复杂情况下,这可能是最简单的解决方案,因为子组件可以通过非动态方式注入到模块的命名空间中祖先模块和查找祖先模块并不是 100% 容易,因为可以使用多种定义继承的方法(使用基础、使用父级、Moose 东西、AUTOLOADED 东西)。

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

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

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

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

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的“经典继承”模块,不适用于驼鹿的东西。如果使用 AutoLoader 调用例程或动态地将例程注入到符号表中,这种情况可能发生在任何代码中(不一定在父代码中),它也不起作用。

This is probably due to the method being inherited from a base class. However, in the extremely weird situations, it COULD also be injected into the module's namespace dynamically which is much harder to figure out.

You can find your sub either by brute force searching or by figuring out the base class of a module (and possibly higher up the inheritance chain) and searching just the base classes code. I will show how to do both:


Brute force search: This is probably the easiest solution in complicated cases since the sub could have been injected into the module's namespace dynamically by non-ancestor module and finding ancestor modules is not 100% easy due to multiple ways of defining inheritance that could have been used (use base, use parent, Moose stuff, AUTOLOADED stuff)

First, find out which other modules are loaded with My::Module

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

This will print the location of ALL those modules

Then, search for the sub definition in ALL that code (the following should be all one line, I split it up for readability into 2 lines):

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

If this returns too many results, change the grep to

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

This will find you the definition in whichever module My::Module::DB::raw_info inherits from without actually analyzing the module code for inheritance.


Inheritance:

Find out the module's parent using ISA as follows:

perl -e 'use My::Module::DB::raw_info; print "@My::Module::DB::raw_info::ISA\n";'

To clarify, this only works for "classically inherited" modules using @ISA, not Moose stuff. It also doesn't work if the routine is called using AutoLoader or is injected into the symbol table dynamically which can happen in any code, not necessarily in the parent one.

烟酉 2024-10-06 13:37:02

造成您的难题的可能原因是 My::Module::DB 扩展了其他一些类。 顶部附近查找块

use parent Some::Module;

BEGIN { extends Some::Module }

沿着My/Module/DB.pm 的顶部

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

The likely cause of your conundrum is that My::Module::DB extends some other class. Look for a block along the lines of

use parent Some::Module;

or

BEGIN { extends Some::Module }

near the top of My/Module/DB.pm

Edit: As some commenters are helpfully pointing out below, there are a number of ways to subclass a Perl class, but these are probably the most common. (Maybe.)

不忘初心 2024-10-06 13:37:02

您可以使用核心 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 为零);
  • 它是在 main 包中编译的;
  • 名称为 MY::top_targets;
  • 在程序的第五个评估中;
  • 当前尚未执行(请参阅深度);
  • 它没有原型(缺少 PROTOTYPE 字段)。

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

You can use the core Devel::Peek module to look at the internal data held in subroutine references.

To obtain a subroutine reference from an OO method, you use the ->can(...) method of all objects.

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

and then you can print out the information:

use Devel::Peek 'Dump';

Dump($code_ref);

According to Devel::Peek's docs, you should get something like this:

A reference to a subroutine looks like this:

    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

This shows that

  • the subroutine is not an XSUB (since START and ROOT are non-zero, and XSUB is zero);
  • that it was compiled in the package main;
  • under the name MY::top_targets;
  • inside a 5th eval in the program;
  • it is not currently executed (see DEPTH);
  • it has no prototype (PROTOTYPE field is missing).

So, COMP_STASH shows you where the code was compiled, and GVGV::GV shows you the sub's full name.

千紇 2024-10-06 13:37:02

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

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

现在查看这些类。

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

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

在输出中查找 GVGV::GV 部分

The method may be defined in the superclasses of My::Module::DB::raw_info. Insert this line before the call to search_like:

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

Now look into these classes.

If this doesn't work, you can use Devel::Peek's Dump() to see where the subroutine came from:

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

Look for GVGV::GV part in the output.

楠木可依 2024-10-06 13:37:02

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

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

In answer to "What I'm not sure of, and I am just learning OOP (thanks to our developer getting fired), is what the "->search_like" refers to.", search_like is a method of the raw_info class that takes name value pairs as its input parameters (Perl Cookbook section 10.7).

FYI, the other book I find very useful is Programming Perl.

岁月染过的梦 2024-10-06 13:37:02

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

Perhaps it's some inherited method. Read a little about Perl inheritance, search for some assignment to @ISA in your module definition.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文