【问题标题】:Damn it, Perl can't bless my object该死,Perl 不能祝福我的对象
【发布时间】:2011-11-14 16:47:50
【问题描述】:

除了双关语,我试图在我的 Perl 类中实现一个 import 方法来实例化一个 Data 对象,该对象本质上是一个美化的 hashrefs 数组,来自适当的 hashrefs 数组。

这是我打算如何使用它的示例:

# Pull in the data
my $data = Data->import(
                         [
                           { a => 1, b => 7, c => 3},
                           { a => 7, b => 9, c => 2},
                         ]
                       );

$data->manipulate;  # Use package methods

我的import实现如下:

package Data;

sub initialize {
    my $class = shift;
    my $data = [];
    bless $data, $class;
    return $data;
}

sub import {

    my ( $class, $data ) = @_;

    bless $data, $class;
    return $data;
}

1;

令人惊讶的是,Perl 在编译-time报告了错误(注意BEGIN 块):

Can't bless non-reference value at Data.pm line 51.
BEGIN failed--compilation aborted at myScript.pl line 8.

perldiag 并没有让事情变得更加清晰:

不能祝福非参考价值

(F) 只有硬引用才能得到祝福。这就是 Perl “强制执行”的方式 对象的封装。看 perlobj.


我什至尝试过在两个单独的步骤中初始化对象并添加数据:

sub import {                         #< Another constructor >

    my ( $class, $data ) = @_;

    my $obj = $class->initialize;
    push @$obj, @$data;

    return $obj;
}

这导致了以下编译时错误:

Can't use an undefined value as an ARRAY reference...
BEGIN failed--compilation aborted at...

两个问题:

  1. 我所做的有什么问题?
  2. 有人可以澄清perldiag 对此编译时错误的解释吗?

【问题讨论】:

  • 后见之明:有没有比perldiag 更好的参考来理解警告/错误消息?
  • 一般来说,您可以通过插入先决条件的打印来解决此类错误。在这种情况下,您的子例程的参数。 (print "import got: @_\n";) 这会让你知道你认为的数组实际上不是。接下来,添加一个警卫,例如ref $data eq 'ARRAY' or confess "not an array: '$data'";,您会发现有问题的电话来自哪里。 (confess 来自 use Carp 'confess'; 并提供完整的回溯)保留该行,因为它可以帮助您在将来立即发现其他错误,可能会将 confess 更改为 croak
  • @Lance Roberts :最初的标题是对Acme::Damn 模块(与bless 的作用相反)的文字游戏

标签: perl bless


【解决方案1】:

import() 给方法起一个危险的名字,因为 Perl 有时会为你调用一个名为“import”的方法。其实声明:

use Data;

真正的意思:

BEGIN {
    require Data;
    Data->import();
}

在“编译”期间发生。

因此,在您有机会使用它之前,您的 import() 方法很可能已被 Perl 作为类加载机制的一部分调用。您应该将 import() 方法重命名为其他名称(例如 import_data),这样就可以了。

【讨论】:

  • 如果是这样,他就不会得到他所得到的错误。
  • 是的,他会的。在这两种情况下,Perl 都会调用 Data->import(),因此 $data 永远不会存在,从而导致“no object to bless”错误和“no array to dereference”错误。
  • +1 :这就是问题所在,将import 重命名为load。我的理智已经恢复。谢谢!
  • 我一直认为import 方法应该是IMPORT 方法与DESTROY 和其他语言块如BEGIN 一起使用。用户/程序员不希望方法的全小写声明 a) 具有与其他任何不同的含义,并且 b) 会导致此问题。
猜你喜欢
  • 2014-01-19
  • 1970-01-01
  • 2011-01-20
  • 2015-11-08
  • 2013-05-04
  • 2011-03-28
  • 2014-07-29
  • 2011-05-04
  • 2014-01-17
相关资源
最近更新 更多