我编写了一个将从主脚本加载的Perl模块.该模块使用在主脚本中定义的子程序(我不是维护者).
对于主脚本中的一个子例程,需要扩展,但我不想修补主脚本.相反,我想覆盖我的模块中的函数并保存对原始子例程的引用.如果调用覆盖,我想调用原始子例程,然后进行一些额外的处理(如果需要).
同情模块代码
my $referenceToOriginalSub;
sub inititialize()
{
$referenceToOriginalSub = \&originalSub;
undef &originalSub;
*originalSub = \&overrideSub;
}
sub overrideSub()
{
#call original within mainscript
&$referenceToOriginalSub(@_);
# do some additional processing if required
}
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为它最终会产生无限递归.显然,参考originalSub也指向它的替代.
所以,请你指出我正确的方向如何避免无限递归?
有一个主要的程序
#! /usr/bin/env perl
use strict;
use warnings;
use MyModule;
sub mainsub {
print "Original mainsub\n";
}
mainsub;
Run Code Online (Sandbox Code Playgroud)
并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;
Run Code Online (Sandbox Code Playgroud)
该INIT块在运行时开始执行程序之前运行.这样做可以在主程序use MyModule的定义之前进行mainsub,并且仍然可以抓住任何副风的处理.
goto $referenceToOriginalSub如果您担心在调用堆栈中屏蔽副作用,则可以使用,但这只允许执行前模式 - 不执行后执行或执行.
输出:
Override: enter Original mainsub Override: leave