【问题标题】:Perl Using a hash as a reference is deprecated when used with package与包一起使用时,不推荐使用 Perl 使用哈希作为参考
【发布时间】:2015-01-29 06:25:13
【问题描述】:

我有一个名为 News 的模块(原名,我知道),它有一个名为 get_fields 的方法,这个方法像这样返回属于该模块的所有字段

sub get_fields {
  my $self = shift;

  return $self;
} 

现在,当我在另一个模块中这样调用它时,我需要对字段进行处理

my %fields = %{ $news->get_fields };

我发现这样做可以避免这个问题

引用键的参数类型必须是 unblessed hashref 或 数组引用

当我像这样迭代其他字段时

foreach my $key ( keys %fields ) {
  %pairs->{$key} = %fields->{$key} if %fields->{$key};
}

为了使用字段的值,我收到此警告

不推荐使用哈希作为参考

它指向foreach循环。

如何在不返回 unbless 警告的情况下避免此错误消息?

【问题讨论】:

  • 经验法则:印记(变量的$%@ 部分)对应于您正在使用的变量的哪一部分。这是$foo{key}$bar[23],因为您访问的是单个值,即使变量是%foo@bar。不是最好的设计,但至少有一个规则。

标签: perl


【解决方案1】:

我认为您在 objectshashes 之间混淆了。 get_fields 将返回 $self - 虽然我无法确定,但看起来它将返回一个受祝福的对象。

现在,祝福对象与哈希非常相似,但它们并不相同。您可以使用ref 函数测试差异。

所以问题更多 - 为什么你这样做?为什么要尝试将对象引用转换为哈希?因为这就是你正在做的事情:

my %fields = %{ $news->get_fields };

因为从根本上说——即使这有效,也将是一件可怕的事情。对象的要点、目的和原因是封装——例如模块外部的东西不干涉内部的东西。

那么为什么不让get_fields 返回一个字段列表,然后您可以对其进行迭代并进行方法调用呢?这确实是做这样的事情的“正确”方式。

sub get_fields {
    my ( $self ) = @_;
    return keys %$self; 
}

或者如果您真的必须,在您的对象中嵌入一个方法,该方法以散列形式返回 - 而不是对象引用 - 然后您可以在外部进行操作。

通常 - 除非您正在操作整个哈希,否则您不会引用带有 % 前缀的哈希。

要从%pairs 中提取单个元素,您应该这样做:

foreach my $key ( keys %pairs ) { 
    print $pairs{$key},"\n";
}

如果$pairs{$key} 的内容是引用,那么您可以使用-> 表示您应该取消引用,例如$pairs -> {$key}

【讨论】:

  • 感谢您的回答。我返回 $self 的原因是为了获取对象的键和值,而不是为每个对象属性设置 getter/setter 方法。但我同意,更正确的方法是使用 getter/setter 或返回 %pairs。
  • 事情是 - OO 对您的编码风格施加了开销。这种开销并不总是值得付出的代价。我们做 OO 的原因根本不是因为效率,而是因为它使代码更健壮并且更容易排除故障,因为问题几乎总是在对象内部或在操纵对象的任何东西中。这是一个有用的优势,这就是 OO 受欢迎的原因,但它只存在于我们保持 OO 范式的情况下——如果你混合搭配,你就会两全其美。有些语言甚至不允许你这样做——Perl 可以,但它仍然是一种糟糕的风格。
  • 我同意,距离我上次使用 Perl 已经 10 多年了,同时我一直在使用大量其他语言,但感谢您的回答:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-12-28
  • 2018-01-07
  • 2018-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多