【问题标题】:How could I redefine a subroutine and keep the old one too?我怎样才能重新定义一个子程序并保留旧的呢?
【发布时间】:2010-12-23 00:32:46
【问题描述】:

这是我想要实现的目标:

sub first {
    print "this is original first";
}

*original_first = \&first;

sub first {
    print "this is first redefined";
}

original_first(); # i expect this to print "this is original first"
first() # i expect this to print "this is first redefined"

我认为通过保存first 的符号,我可以稍后调用原始子例程(名称为original_first),也可以调用first,并重新定义一个.但是,如果我调用original_first,我仍然会得到“这是第一次重新定义”。我必须做什么才能完成这项工作?

【问题讨论】:

    标签: perl symbols redefinition


    【解决方案1】:

    这应该可以如您所愿:

    sub first {
        print "this is original first";
    }
    
    *original_first = \&first;
    
    *first = sub {
        print "this is first redefined";
    };
    

    【讨论】:

    • 当您重新定义first 符号时,是否可能只影响代码部分?
    • 将 coderef(由 sub{...} 生成)分配给 typeglob 只会替换 glob 中的 CODE 条目。 glob 中的任何其他数据类型都不会改变
    • 您也可以使用local *first = sub {...}; 仅替换特定块内的功能。
    【解决方案2】:

    在您的代码中,Perl 解释这两个子声明类似于:

    BEGIN {
        *first = sub { ... }
    }
    

    所以对&first 的两个分配最终都会在保存副本和调用例程之前发生。解决方法是将第二个声明变成运行时赋值:

    sub first {
        print "this is original first";
    }
    
    *original_first = \&first;
    
    *first = sub {print "this is first redefined"};
    
    original_first(); # prints "this is original first"
    first();          # prints "this is first redefined"
    

    【讨论】:

    • sub {} 所需的引用 -> BEGIN { *... } 您描述的行为。
    • 我从 perlmod 的以下解释中推断出上述内容:子例程定义(和声明,就此而言)不一定位于它们占用的符号表的包中。您可以通过显式限定子例程的名称在其包之外定义子例程: 1. package main; 2. sub Some_package::foo { ... } # &foo 定义在 Some_package 这只是编译时 typeglob 赋值的简写: 1. BEGIN { *Some_package::foo = sub { ... } }
    【解决方案3】:

    查看Hook::LexWrap 模块,它可以为您处理所有这些。如果您不想使用该模块,只需查看源代码,它会告诉您确切的操作方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-11-04
      • 1970-01-01
      • 1970-01-01
      • 2014-12-04
      • 2021-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多