为非对象perl模块复制base / parent.pm功能的最简洁方法是什么?

前端之家收集整理的这篇文章主要介绍了为非对象perl模块复制base / parent.pm功能的最简洁方法是什么?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我现在不太清楚,可能会忽略一些简单的事情.我已经考虑了一段时间并一直在寻找,但不能再想到任何明智的搜索查询会导致我找到我想要的东西.

简而言之,我想知道如何进行模块继承,就像base.pm/parent.pm为面向对象模块做的那样;仅适用于基于Exporter的模块.

我的意思的一个假设的例子:

这是我们的脚本.它最初加载了Foo.pm并从中调用了baz(),但是baz()有一个可怕的bug(我们很快就会看到),所以我们现在使用Local / Patched / Foo.pm来解决这个问题.我们这样做,因为在这个假设的情况下我们不能改变Foo(它是一个正在积极开发的cpan模块,你看),并且它是巨大的(严重的).

#!/usr/bin/perl

# use Foo qw( baz [... 100 more functions here ...] );
use Local::Patched::Foo qw( baz [... 100 more functions here ...] );
baz();

这是Foo.pm.正如你所看到的,它导出了调用qux的baz(),它有一个可怕的bug,导致事情崩溃.我们希望保留baz和Foo.pm的其余部分,但没有做大量的复制粘贴,特别是因为它们可能会在以后更改,因为Foo仍在开发中.

package Foo;
use parent 'Exporter';
our @EXPORT = qw( baz [... 100 more functions here ...] );
sub baz { qux(); }
sub qux { print 1/0; }            # !!!!!!!!!!!!!
[... 100 more functions here ...]
1;

最后,由于Foo.pm用于很多地方,我们不想使用Sub :: Exporter,因为这意味着将bandaid修复程序复制粘贴到所有这些地方.相反,我们正在尝试创建一个新的模块,其行为和看起来像Foo.pm,并且实际上仍然从Foo.pm加载其99%的功能,并用更好的一个替换丑陋的qux子.

接下来是如果Foo.pm是面向对象的,那么这样的事情会是什么样子:

package Local::Patched::Foo;
use parent 'Foo';
sub qux { print 2; }
1;

现在这显然不适用于我们目前的情况,因为parent.pm只是不做这种事情.

是否有一种干净而简单的方法来编写Local / Patched / Foo.pm(使用任何适用的CPAN模块),这种方法可以工作,而不是手动复制Foo.pm的函数命名空间?

解决方法

只是添加了另一种方法来修补Foo的qux函数,这个没有任何手动typeglob操作.
package Local::Patched::Foo;
use Foo (); # load but import nothing

sub Foo::qux {
    print "good qux";
}

这是有效的,因为Perl的包总是可变的,只要上面的代码在加载Foo.pm后出现,它就会覆盖现有的baz例程.你可能也不需要警告’重新定义’;沉默任何警告.

然后使用它:

use Local::Patched::Foo;
use Foo qw( baz );

baz();  # calls the patched qux() routine

您可以通过在Local :: Patched :: Foo中编写自定义导入方法来消除这两个使用行,如下所示:

# in the Local::Patched::Foo package:

sub import {
    return unless @_;             # return if no imports
    splice @_,1,'Foo';       # change 'Local::Patched::Foo' to 'Foo'
    goto &{ Foo->can('import') }; # jump to Foo's import method
}

然后就是:

use Local::Patched::Foo qw( baz );

baz();  # calls the patched qux()

猜你在找的Perl相关文章