perl - 如何在我自己的包中重新定义子,但从新包中访问旧包
问题描述
我有一些代码文件开始像
use my_pck;
BEGIN {
package my_pck;
my(@p) = ();
foreach ( keys(%my_pck::) ) {
push( @p, "\$$_" ) if (defined $$_);
push( @p, "\%$_" ) if (%$_);
push( @p, "\@$_" ) if (@$_);
}
# ... some extra
( @EXPORT = @p, Exporter::import pal ) if ( $#p >= 0 );
}
use strict;
use warnings;
package my_pck;
这部分我不能改变(除了在“一些额外的”处添加一些东西)。
所以现在它里面有一个名为“my_today”的子,因为我需要package my_pck
在源文件中使用它在任何地方都可用和经常使用。此方法以“YYYYMMDD”格式给出当前日期。
要检查前一天的一些测试数据,我需要重新定义此方法以提供前一天。
我试图重新定义它
sub my_today {
my $date = my_pck::my_today();
$date = my_datefunc($date, "-", 1) # substracts one day
return $day;
}
但所以我得到一个错误:
Subroutine my_today redefined at ./my_file.pl line 123.
Deep recursion on subroutine "my_pck::my_today" at ./my_file.pl line 124.
Out of memory!
我该如何解决这个问题?我无法更改整个代码,因为它太多了。
解决方案
你通常想要
{
my $old_my_today = \&my_pck::mytoday;
my $new_my_today = sub { my_pck::my_datefunc($old_my_today->(), "-", 1) };
no warnings qw( redefine );
*my_pck::mytoday = $new_my_today;
}
问题是新代码必须出现在被替换的 sub 之前,但是我们需要在编译完模块的其余部分之后执行它。为此,我们将使用UNITCHECK
.
UNITCHECK
块在定义它们的单元被编译之后运行。主程序文件和它加载的每个模块都是编译单元,字符串eval
s、使用正则表达式中的构造编译的运行时代码、对、(?{ })
的调用以及命令行上切换后的代码也是如此。do FILE
require FILE
-e
UNITCHECK {
my $old_my_today = \&my_pck::mytoday;
my $new_my_today = sub { my_pck::my_datefunc($old_my_today->(), "-", 1) };
no warnings qw( redefine );
*my_pck::mytoday = $new_my_today;
}
演示
my_pck.pm
:
BEGIN {
UNITCHECK {
my $old_my_today = \&my_pck::mytoday;
my $new_my_today = sub { my_pck::my_datefunc($old_my_today->(), "-", 1) };
no warnings qw( redefine );
*my_pck::mytoday = $new_my_today;
}
}
package my_pck;
sub mytoday { 20211011 }
sub my_datefunc { $_[0] - 1 }
1
$ perl -I . -M5.010 -e'use my_pck; say my_pck::mytoday'
20211010
(BEGIN
绝对没有必要;它只是为了表明UNITCHECK
可以在您描述的情况下使用。)
推荐阅读
- c - 在不支持 GLSL 的情况下在屏幕/纹理中查找最大最小像素亮度
- spring-boot - 有没有办法创建包含插件的共享 Gradle 文件?
- java - 从 Java 1.8 中的 org.w3c.dom.Attr 获取值的一般方法?
- c# - 如何使用 MVVM 模式绑定 Datagrid?
- c# - 64 位 VSTO 需要作为 64 位 DLL 的 Office 开发人员工具?
- machine-learning - 功能选择 - 当您有太多功能时如何进行?
- rust - 将值附加到 rust 宏中的 args
- python - 如何比较签名?
- redirect - Bigcommerce 在购物车页面上重定向
- terraform - 如何在 Terraform 中获取调用模块的名称