Perl 从类子例程重写模块子例程
我有一个类,它能够定义凭据Perl 从类子例程重写模块子例程,perl,Perl,我有一个类,它能够定义凭据 $po=posservice->new()->set_basicauth(“杰克”、“秘密”); 问题是,为了做到这一点,它必须重新定义一个模块子例程。所以,我是这样做的: subset\u basicauth{ 我的($self、$creds\u用户名、$creds\u密码)=@; 子SOAP::传输::HTTP::客户端::获取基本凭据{ 返回$creds\u username=>$creds\u password; } 返回$self; } 但是,当我运行代
$po=posservice->new()->set_basicauth(“杰克”、“秘密”);
问题是,为了做到这一点,它必须重新定义一个模块子例程。所以,我是这样做的:
subset\u basicauth{
我的($self、$creds\u用户名、$creds\u密码)=@;
子SOAP::传输::HTTP::客户端::获取基本凭据{
返回$creds\u username=>$creds\u password;
}
返回$self;
}
但是,当我运行代码时,它会告诉我一条消息:
Variable "$creds_username" will not stay shared at /opt/PoService.pm line 53.
Variable "$creds_password" will not stay shared at /opt/PoService.pm line 53.
我做错了什么?问题是词法(
my
)变量和嵌套子例程的混合
内部子例程关闭它使用的两个变量。然而,由于词法上的原因,它们在每次新调用时都会被重新定义,而内部(命名)子对象忠实地保持对原始值的引用。因此,只有在第一次调用时,整个过程才可能像预期的那样工作
幸运的是,我们得到了这一事实的警告。使用进行诊断代码>已添加(或请参阅)
变量“$x”将不会在-e第1行(#1)上共享
(W闭包)内部(嵌套)命名子例程正在引用
在外部命名子例程中定义的词法变量
当调用内部子例程时,它将看到
外部子例程的变量在第一次
调用外部子例程;在这种情况下,在第一次调用
外部子例程完成后,内部子例程和外部子例程将不再显示
更长时间共享变量的公共值。换句话说
变量将不再被共享
这个问题通常可以通过制作内部子程序来解决
匿名,使用sub{}语法。当内部匿名潜艇
创建外部子例程中的引用变量时
自动恢复到此类变量的当前值
虽然这解释了问题,但如果我理解正确的话,这个解决方案对你来说是行不通的
一种似乎合适的方法是完全限定名称
sub SOAP::Transport::HTTP::Client::get_basic_credentials {
return $main::$creds_username => $main::$creds_password;
}
sub set_basicauth {
my $self = shift;
($main::$creds_username, $main::$creds_password) = @_;
# ... (not sure of your purpose, presumably use SOAP::)
return $self;
}
其中,$main
应替换为实际的包名(如果不同)。sub可以放置在另一个sub中,但没有任何用途,因为它是作为任何其他命名sub编译的
另一种选择是使用全局变量。没有嵌套命名子类
sub set_basicauth {
my ($self, $username, $password) = @_;
$self->{username} = $username;
$self->{password} = $password;
}
sub request {
my ($self, ...) = @_;
my $username = $self->{username};
my $password = $self->{password};
local *SOAP::Transport::HTTP::Client::get_basic_credentials = sub {
return $username => $password;
};
... code that uses SOAP::Lite ...
}
谢谢@zdim。我已将解决方案修改为有效解决方案。@sancho21 Great:)。谢谢你的建议编辑。然而,声明my
vars是另一回事。它引入了一个词汇表,在这种情况下,它实际上是全局的(无论如何,在更大的范围内)。如果您随后引用它($var
),那么它就是词法,而不是$main::var
——您总是要调用$main::var
。$main::var
在符号表中创建一个条目(而my$var
不创建)。当完全合格时,它们不需要被声明(如果它不起作用,肯定还有其他原因)。我将添加一些评论或链接(但稍后,现在在这里已经太晚了)。