2011-04-08 73 views
10

我最近看到一些使我困惑的Perl代码。我拿出所有额外的部件来看看它是如何工作的,但我仍然不明白它为什么起作用。如何调用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; 

我认为这是行不通的,因为“acquire”子是n曾经出口过。但它确实有效。 我的“TTT”的号召,收购后困惑,所以我删除了,留下了一行:

my $tt = acquire; 

它抱怨裸字的,像我想的那样。我加了括号,就像这样:

my $tt = acquire(); 

它抱怨说,没有一个main::acquire,像我想的那样。

我习惯了可用于对象的子例程,或者正在导出的子例程,但是我从来没有看到过使用包名称调用的子例程。我甚至不知道如何在Google上搜索这些内容。

所以我的问题是,子程序调用后如何添加包名称工作?我从来没有见过类似的东西,这可能不是一个好习惯,但是有人可以解释Perl正在做什么吗?

谢谢!

回答

11

您正在使用Perl允许的间接对象语法(但不鼓励在现代代码中使用)。基本上,如果名称不是预先声明的,它可以放在用空格分隔的对象(或类名称)的前面。

所以行acquire TTT其实意味着TTT->acquire。如果实际上在范围内有一个名为acquire的子程序,它将被解释为aquire(TTT),这可能会导致模糊(因此为什么不鼓励)。

你也应该在方法更新new TTT();行改为TTT->new;

+0

非常感谢 - 现在总感觉! – BrianH 2011-04-08 16:07:28

6

这是方法调用indirect object syntax,它可以让你把方法名称之前的对象名称。

如文档有演出,所以最好避免,因为它的笨重,它可以在不可预知的方式划分,例如,如果有导入或定义子程序命名为acquire - 但它使用的是较常见的比今天,所以你会经常在旧的代码和文档中找到它。

+0

的有点,仍然批准的使用这句法的是一个包的'new'方法,所以你可以说'$ OBJ =新Object'而不是'$ obj = Object :: new'。这有助于C++程序员认为他们知道发生了什么。 – mob 2011-04-08 15:48:52

+0

感谢您的解释,@ hobbs - 现在有很多意义! – BrianH 2011-04-08 16:07:45

+3

@mob:我认为“有点”是指“人们会发牢骚,但可能不会破坏你的膝盖。”太多人认为'new object'中的'new'是一个关键词,只是一个约定。 – 2011-04-08 16:20:52