perl中“defined%{”some :: string“}”的含义

时间:2014-03-19 10:42:03

标签: perl refactoring warnings

我正在将我的应用程序从Perl 5.8.8切换到Perl 5.16.3,现在我收到大量关于SOAP :: Lite中的以下第三方代码的警告

unless (defined %{"$protocol_class\::Client::" )

代码产生以下警告:

Warning in Perl code: \t(Maybe you should just omit the defined()?)
Warning in Perl code: defined(%hash) is deprecated at /.../SOAP/Lite.pm
line ...

如果我把它简化为一个简单的例子,它看起来像

unless( defined %{"some::string"} )

问题:为什么有人会解释字符串" some :: string"作为哈希%{" some :: string"}并检查是否定义了哈希?它对我没有任何意义。我想用其他东西替换这个代码而不破坏第三方模块,这样我就可以专注于真正重要的警告和错误。

这是整个功能。我不知道这是否有帮助,因为认为某种Guru代码有点难以理解

sub proxy {
    my $self = shift;
    $self = $self->new() if not ref $self;

    my $class = ref $self;

    return $self->{_proxy} unless @_;

    $_[0] =~ /^(\w+):/ or die "proxy: transport protocol not specified\n";
    my $protocol = uc "$1"; # untainted now

    # HTTPS is handled by HTTP class
    $protocol =~s/^HTTPS$/HTTP/;

    (my $protocol_class = "${class}::$protocol") =~ s/-/_/g;

    no strict 'refs';
    unless (defined %{"$protocol_class\::Client::"}
        && UNIVERSAL::can("$protocol_class\::Client" => 'new')
    ) {
        eval "require $protocol_class";
        die "Unsupported protocol '$protocol'\n"
            if $@ =~ m!^Can\'t locate SOAP/Transport/!;
        die if $@;
    }

    $protocol_class .= "::Client";
    return $self->{_proxy} = $protocol_class->new(endpoint => shift, @_);
}

1 个答案:

答案 0 :(得分:1)

构造%Package::可以访问包的存储,即符号表哈希。

所有这些代码正在检查是否已经加载了给定的包(在这种情况下它的存储将存在),并且该包有一个new方法。如果没有,则require用于加载模块。

UNIVERSAL::can('package', 'method')的调用通常写为'package'->can('method'),如果您愿意,可以在此处更改,但代码将按原样运行。

我建议你像警告一样说,并省略defined。如果将包名称放在自己的变量中而不是使用插值的双引号字符串两次也会更好,并且您可以使用我所描述的常规调用can。它看起来像这样

my $package = "${protocol_class}::Client";
unless ( %{"${package}::"} and $package->can('new') ) {

  # load missing module
}