5

我编写了一个将从主脚本加载的 Perl 模块。该模块使用在主脚本中定义的子程序(我不是维护者)。

对于主脚本中的一个子例程,需要扩展,但我不想修补主脚本。相反,我想覆盖我的模块中的函数并保存对原始子例程的引用。如果调用了覆盖,我想调用原来的子程序,然后做一些额外的处理(如果需要的话)。

符号模块代码

my $referenceToOriginalSub;

sub inititialize()
{
    $referenceToOriginalSub = \&originalSub;
    undef &originalSub;
    *originalSub = \&overrideSub;
}

sub overrideSub()
{
    #call original within mainscript
    &$referenceToOriginalSub(@_);
    # do some additional processing if required
}

这不起作用,因为它以无限递归结束。显然,引用originalSub也指向它的替代。

那么,您能否指出正确的方向如何避免无限递归?

4

1 回答 1

7

有一个主程序

#! /usr/bin/env perl

use strict;
use warnings;

use MyModule;

sub mainsub {
  print "Original mainsub\n";
}

mainsub;

MyModule.pm包含

package MyModule;

use strict;
use warnings;

my $referenceToOriginalSub;

sub overrideSub {
  print "Override: enter\n";

  $referenceToOriginalSub->(@_);
  # alternative:
  # goto $referenceToOriginalSub;

  print "Override: leave\n";
}

INIT {
  no warnings 'redefine';
  $referenceToOriginalSub = \&main::mainsub;
  *main::mainsub = \&overrideSub;
}

1;

INIT块在运行时开始执行程序之前运行。这样做允许在主程序中use MyModule的定义之前出现,mainsub并且仍然能够掌握子程序的任何内容。

goto $referenceToOriginalSub如果您担心在调用堆栈中屏蔽副作用,您会使用,但这仅允许执行前模式 - 不允许执行后或执行周围。

输出:

覆盖:输入
原始主子
覆盖:离开
于 2013-08-31T18:38:52.843 回答