我编写了一个将从主脚本加载的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的引用也指向它的替代.
所以,请你指出正确的方向如何避免无限递归?
解决方法
有一个主要的程序
#! /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块在运行时开始执行程序之前运行.这样做允许使用MyModule来在主程序中定义mainsub之前,并且仍然可以抓住任何子风的句柄.
如果您担心在调用堆栈中屏蔽副作用,则可以使用goto $referenceToOriginalSub
,但这只允许执行前模式 – 不执行后执行或执行.
输出:
Override: enter Original mainsub Override: leave