拦截Perl中不存在的方法调用

时间:2011-08-04 08:32:58

标签: perl autoload

我尝试在某些子类中拦截不存在的方法调用。 是的,我知道AUTOLOAD, 但是(对于方法)它首先尝试调用parent ::方法,然后调用UNIVERSAL ::方法然后调用:: AUTOLOAD。 但我首先需要调用(例如):: AUTOLOAD。 因为我想知道子类尝试从父类调用什么方法。

请给我一些建议。

3 个答案:

答案 0 :(得分:1)

  • 如果您只想知道正在使用哪些方法,可以使用一些分析模块,如Devel :: NYTProf。

  • 如果您想在程序执行期间对此做出反应,您可以像剖析模块一样直接拦截井上操作码。有关更多详细信息,请参阅perlguts或profiling模块代码。

  • 您可以使用FETCH和EXISTS创建一个'Monitor'类,并将其绑定到符号表哈希,如:tie%Module :: Name ::,Monitor;

但除非我们确切地知道你要做什么以及为什么,否则很难猜出什么是适合你的解决方案。

答案 1 :(得分:1)

请大力考虑Jiri Klouda建议你退后一步,重新考虑你想要完成的事情。你几乎从不想做你想做的事。

但是,如果你确实确定你想要,那么就是如何获得足够纯粹的Perl绳索让自己挂起......

subs pragma将预先列出的子名称列表。正如tchrist所说,你可以预先确定潜艇,但从未真正定义它们。这将短路方法分配到超类并立即调用您的AUTOLOAD。

至于要传递给编译指示的子名称列表,您可以使用Class::Inspector->methods(感谢Nic Gibson's answer教我这个模块。)

根据brian d foy对Nic Gibson的回答的评论,Class :: Inspector将不会处理UNIVERSAL中定义的方法。如果您需要单独执行这些操作,可以从我的Class::LazyObject模块中的“use subs”行获取灵感。

答案 2 :(得分:0)

为什么不在子类包中创建一个AUTOLOAD子,1)报告丢失的方法然后2)将调用分派给父类。为此,在子类中定义@ISA

类似的东西:

package my_parent;

sub foo { warn "in my_parent::foo" }

package my_subclass;

my $PARENT_CLASS = "my_parent"; # assume only one parent

# Note: no @ISA defined here

sub AUTOLOAD {
  warn "non-existent method $AUTOLOAD called\n";
  my $self = shift;
  (my $method = $AUTOLOAD) =~ s{.*::}{};
  my $super = $PARENT_CLASS . '::' . $method;
  $self->$super(@_);
}

package main;

my $x = bless {}, 'my_subclass';
$x->foo;

语法:$self->$super(@_)其中$super有双冒号,告诉perl在哪个包中开始寻找方法,例如:

$self->my_parent::foo(...)

将在foo包中开始查找my_parent方法,而不管哪个类$self被祝福。