9

执行语句$obj->method();时,perldiag表示 Perl 需要知道该方法属于哪个包。这就是为什么它需要被祝福:

无法在 unblessed 引用上调用方法“%s”

(F) 方法调用必须知道它应该在哪个包中运行。它通常从您提供的对象引用中发现这一点,但在这种情况下您没有提供对象引用。在得到祝福之前,引用不是对象引用。见 perlobj

因此,无法执行以下操作:

my $data = [
             [ 1, 2, 3 ],
             [ 4, 5, 6 ],
           ];

$data->process( @params );  # Can't call method "process" on unblessed reference

那为什么它可以与 coderef 一起使用?:

my $process = \&process;    # Same method as before
$data->$process( @params ); # Works fine now
4

3 回答 3

22
$variable->method(@args)

只是调用

method($variable, @args)

但是 Perl 应该在哪个包中找到method子例程?如果$variable是一个祝福引用,Perl 将在ref $variable. 如果$variable是一个字符串和一个包的名称,Perl 将在该包名称中查找子例程。

在你的第二个例子中,当你声明

$process = \&process

你已经给 Perl 引用了你想要调用的代码,所以 Perl 知道接听电话

$variable->$process(@args)

并调用

$process->($variable, @args)

或者

&process($variable, @args)

只有当$variable是一个unblessed引用,并且方法名称无法解析为代码引用时,Perl 才不知道该做什么和下注。

于 2011-11-14T18:43:22.593 回答
10

当 perl 看到$x->$y它时,它会将其编译成如下内容:

if (reftype $y eq 'CODE') {
    $y->($x)
}
else {
    if (my $code_ref = eval {$x->can($y)}) {
        $code_ref->($x)
    }
    else {
       die "error"
    }
}

如果$y碰巧是一个bareword,第一次检查总是假的,然后else块执行一个正常的方法调用。

于 2011-11-14T19:24:08.993 回答
6

在第一个示例中,您尝试按名称调用数组引用的方法;数组引用没有任何方法,所以这甚至没有意义。

在第二个示例中,您使用了类似的语法,但在这种情况下,这->只是将左侧参数作为第一个参数调用右侧参数的语法糖;它不是调用实例方法,它只是调用具有以令人困惑的方式指定的参数的子例程。

于 2011-11-14T18:38:24.753 回答