我最近看到一些让我困惑的Perl代码。我拿出了所有额外的部分,看看它是如何工作的,但我仍然不明白它为什么会起作用。
基本上,我创建了这个虚拟“模块”(TTT.pm):
use strict;
use warnings;
package TTT;
sub new {
my $class = shift;
return bless {'Test' => 'Test'}, $class;
}
sub acquire {
my $tt = new TTT();
return $tt;
}
1;
然后我创建了这个脚本来使用模块(ttt.pl):
#!/usr/bin/perl
use strict;
use warnings;
use TTT;
our $VERSION = 1;
my $tt = acquire TTT;
print $tt->{Test};
令我感到困惑的是,我认为不行,是:
my $tt = acquire TTT;
我认为它不起作用,因为“获取”子从未导出过。但它确实有效。 收到电话后,我对“TTT”感到困惑,所以我将其删除,留下这样的一行:
my $tt = acquire;
它抱怨了一句话,就像我想的那样。我添加了parens,像这样:
my $tt = acquire();
它抱怨没有main::acquire
,就像我想的那样。
我已经习惯了对象可用的子程序,或者正在导出的子程序,但我从未见过最后用包名调用子程序。我甚至不知道如何在Google上搜索此内容。
所以我的问题是,在子程序调用之后如何添加包名?我之前从未见过这样的事情,这可能不是很好的做法,但有人可以解释一下Perl在做什么吗?
谢谢!
答案 0 :(得分:11)
您正在使用Perl允许的间接对象语法(但不鼓励使用现代代码)。基本上,如果名称不是预先声明的,它可以放在用空格分隔的对象(或类名)前面。
因此,行acquire TTT
实际上意味着TTT->acquire
。如果你在范围内实际上有一个名为acquire
的子程序,那么它将被解释为aquire(TTT)
,这可能导致歧义(因此不鼓励它)。
您还应该更新方法中的new TTT();
行,以便阅读TTT->new;
答案 1 :(得分:6)
这是方法调用的indirect object syntax,它允许您将方法名放在对象名之前。
正如文档中所示,最好避免使用它,因为它不实用且可能以不可预测的方式中断,例如,如果是导入或定义的名为acquire
的子例程 - 但它使用了比现在更常见,所以你会经常在旧的代码和文档中找到它。