如何在 Perl 中修补实例方法? [英] How can I monkey-patch an instance method in Perl?
问题描述
我正在尝试修补 (duck-punch :-) LWP::UserAgent
实例,如下所示:
I'm trying to monkey-patch (duck-punch :-) a LWP::UserAgent
instance, like so:
sub _user_agent_get_basic_credentials_patch {
return ($username, $password);
}
my $agent = LWP::UserAgent->new();
$agent->get_basic_credentials = _user_agent_get_basic_credentials_patch;
这不是正确的语法——它会产生:
This isn't the right syntax -- it yields:
不能修改非左值子程序在 [module] 行 [lineno] 调用.
Can't modify non-lvalue subroutine call at [module] line [lineno].
我记得(来自 Programming Perl),调度查找是基于受祝福的包动态执行的(ref($agent)
,我相信),所以我我不确定实例猴子补丁如何在不影响祝福包的情况下工作.
As I recall (from Programming Perl), dispatch lookup is performed dynamically based on the blessed package (ref($agent)
, I believe), so I'm not sure how instance monkey patching would even work without affecting the blessed package.
我知道我可以对 UserAgent
进行子类化,但我更喜欢更简洁的猴子补丁方法.同意成年人和你有什么.;-)
I know that I can subclass the UserAgent
, but I would prefer the more concise monkey-patched approach. Consenting adults and what have you. ;-)
推荐答案
如果动态范围(使用local
)不令人满意,您可以自动化自定义包reblessing技术:
If dynamic scope (using local
) isn't satisfactory, you can automate the custom package reblessing technique:
MONKEY_PATCH_INSTANCE:
{
my $counter = 1; # could use a state var in perl 5.10
sub monkey_patch_instance
{
my($instance, $method, $code) = @_;
my $package = ref($instance) . '::MonkeyPatch' . $counter++;
no strict 'refs';
@{$package . '::ISA'} = (ref($instance));
*{$package . '::' . $method} = $code;
bless $_[0], $package; # sneaky re-bless of aliased argument
}
}
示例用法:
package Dog;
sub new { bless {}, shift }
sub speak { print "woof!
" }
...
package main;
my $dog1 = Dog->new;
my $dog2 = Dog->new;
monkey_patch_instance($dog2, speak => sub { print "yap!
" });
$dog1->speak; # woof!
$dog2->speak; # yap!
这篇关于如何在 Perl 中修补实例方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!