从模块调用子例程时,我一直与::
混淆->
。我知道::
与路径更相关,模块/子程序在哪里,->
用于对象,但我真的不明白为什么我看似可以互换两者而且没有提出来即时错误。
我有perl模块,它们是更大包装的一部分,例如FullProgram::Part1
我只是想要掌握模块,但是当谈到Perl对象时,我仍然处于不稳定状态,但我不小心这样做了:
FullProgram::Part1::subroutine1();
而不是
FullProgram::Part1->subroutine1();
所以当我将散列引用传递给子程序1并小心使用$class/$self
来处理对象引用并意外地使用::
时,我最后拉出我的头发想知道为什么我的哈希ref似乎消失了。我已经吸取了教训,但我真的想解释一下这种差异。我已经阅读了perldocs和各种网站,但我没有看到两者之间的任何比较(相当难以谷歌...)
所有的帮助表示赞赏 - 总是很了解我在做什么!
答案 0 :(得分:9)
香草子和一种方法之间没有固有的区别。这就是你如何称呼它。
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');
答案 1 :(得分: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
的值,这是您最初传递给method
@args
的{{1}}的第二个列表元素}。这样对象本身就不会丢失。
有关调用方法时继承树如何变得重要的更多信息,请参阅ikegami's answer!
答案 2 :(得分:5)
同时使用!
use Module::Two;
Module::Two::->class_method();
请注意,这样可以保护您免受歧义的影响;简单的
Module::Two->class_method();
将被解释为:
Module::Two()->class_method();
(在Module中调用子例程2并尝试在其返回值上调用class_method - 可能导致运行时错误或在某个完全不同的类中调用类或实例方法) if 是模块中的二分之一 - 你不应该依赖于这种或那种方式,因为它不是你的代码的业务中的任何一个在模块中。
答案 3 :(得分:0)
历史上,Perl没有任何OO。和使用FullProgram::Part1::subroutine1();
sytax调用的包中的函数。甚至在使用FullProgram'Part1'subroutine1();
语法之前(不建议使用)。
后来,他们用->
符号实现了OOP,但实际上并没有太多改变。 FullProgram::Part1->subroutine1();
次调用subroutine1
和FullProgram::Part1
作为第一个参数。您可以在创建对象时看到此用法:my $cgi = CGI->new()
。现在,当您从此对象调用方法时,左侧部分也作为第一个参数运行:$cgi->param('')
。这就是param
如何获取他调用的对象(通常命名为$self
)。而已。 ->
是OOP的黑客攻击。因此,Perl没有类(包作为它们),但确实有对象(“对象”也是hacks - 它们是受祝福的标量)。
Offtop:您也可以使用my $cgi = new CGI;
语法进行调用。这与CGI->new
相同。当你说print STDOUT "text\n";
时也一样。是的,只需致电IOHandle::print()
。