8

从模块调用子例程时,我一直感到::困惑。->我知道这::与路径以及模块/子例程在哪里以及->用于对象的位置更相关,但我真的不明白为什么我似乎可以互换两者并且不会立即出现错误。我有 perl 模块,它们是更大包的一部分,例如FullProgram::Part1

我只是要掌握模块,但在涉及 Perl 对象时仍然处于不稳定的状态,但我一直不小心这样做:

FullProgram::Part1::subroutine1();

代替

FullProgram::Part1->subroutine1();

因此,当我一直将哈希引用传递给 subroutine1 并小心使用$class/$self来处理对象引用并意外使用::时,我最终拉出我的头发,想知道为什么我的哈希引用似乎消失了。我已经吸取了教训,但真的很想解释一下差异。我已经阅读了关于这些的 perldocs 和各种网站,但我没有看到两者之间的任何比较(谷歌很难......)所有帮助表示赞赏 - 总是很高兴了解我在做什么!

4

4 回答 4

9

vanilla sub和一个方法之间没有内在的区别。这一切都在你如何称呼它。


Class::foo('a');

这将调用Class::foo. 如果Class::foo不存在,则不会检查继承树。Class::foo将仅传递提供的参数 ( 'a')。

它与以下内容大致相同:my $sub = \&Class::foo; $sub->('a');


Class->foo('a');

这将调用Class::foo, 或foo在其基类之一中调用(如果Class::foo不存在)。调用者(左边的->)将作为参数传递。

它与以下内容大致相同:my $sub = Class->can('foo'); $sub->('Class', 'a');

于 2012-11-20T18:08:47.560 回答
7
FullProgram::Part1::subroutine1();

调用带有空参数列表subroutine1的包的子例程,而FullProgram::Part1

FullProgram::Part1->subroutine1();

使用包名称作为第一个参数调用相同的子例程(请注意,当您进行子类化时它会变得有点复杂)。此语法由需要类名来构建子类对象的构造函数使用,例如

sub new {
    my ($class, @args) = @_;
    ...
    return bless $thing, $class;
}

仅供参考:在 Perl OO 中,您会看到$object->method(@args)哪些调用Class::method以对象(祝福引用)作为第一个参数而不是包/类名。在这样的方法中,子程序可以这样工作:

sub method {
    my ($self, $foo, $bar) = @_;
    $self->do_something_with($bar);
    # ...
}

它将do_something_with再次以对象作为第一个参数调用子例程,然后$bar是您最初传递给methodin的第二个列表元素的值@args。这样对象本身就不会丢失。

有关调用方法时继承树如何变得重要的更多信息,请参阅ikegami 的回答

于 2012-11-20T18:08:37.797 回答
5

两者都用!

use Module::Two;

Module::Two::->class_method();

请注意,这有效,但也可以保护您免受歧义;简单的

Module::Two->class_method();

将被解释为:

Module::Two()->class_method();

(在 Module 中调用子例程 Two 并尝试在其返回值上调用 class_method - 可能导致运行时错误或调用某个完全不同的类中的类或实例方法)如果Module 中恰好有一个 sub Two - 你不应依赖于一种或另一种方式,因为Module 中的内容与您的代码无关。

于 2012-11-20T19:57:03.573 回答
0

从历史上看,Perl 没有任何 OO。以及使用FullProgram::Part1::subroutine1();sytax 调用的包中的函数。甚至在使用FullProgram'Part1'subroutine1();语法之前(已弃用)。

后来,他们用->符号实现了OOP,但实际上并没有太大变化。FullProgram::Part1->subroutine1();调用subroutine1FullProgram::Part1作为第一个参数。您可以在创建对象时看到它的用法:my $cgi = CGI->new(). 现在,当您从此对象调用方法时,左侧部分也作为函数的第一个参数:$cgi->param('')。这就是如何param获取他调用的对象(通常命名为$self)。就是这样。->是面向 OOP 的 hack。因此,Perl 没有类(包像它们一样工作),但确实有对象(“对象”也被破解了——它们是有福的标量)。

Offtop:您也可以使用my $cgi = new CGI;语法调用。这与CGI->new. 你说的也一样print STDOUT "text\n";。是的,只是打电话IOHandle::print()

于 2012-11-20T18:18:17.953 回答