当从Perl模块调用方法时,为什么'::'和' - >'可以互换工作?

dgB*_*gBP 8 oop perl module

从模块调用子程序时,我一直很::困惑->.我知道这::与路径以及模块/子程序->用于对象的位置有关,但我真的不明白为什么我看似可以互换它并且它没有立即出现错误.我有perl模块,它们是更大包装的一部分,例如FullProgram::Part1

我只是想要掌握模块,但是当谈到Perl对象时仍然处于不稳定状态,但我不小心这样做了:

FullProgram::Part1::subroutine1();
Run Code Online (Sandbox Code Playgroud)

代替

FullProgram::Part1->subroutine1();
Run Code Online (Sandbox Code Playgroud)

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

ike*_*ami 9

香草子和一种方法之间没有固有的区别.这就是你如何称呼它.


Class::foo('a');
Run Code Online (Sandbox Code Playgroud)

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

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


Class->foo('a');
Run Code Online (Sandbox Code Playgroud)

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

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


mem*_*owe 7

FullProgram::Part1::subroutine1();
Run Code Online (Sandbox Code Playgroud)

使用空参数列表调用subroutine1包的子例程FullProgram::Part1

FullProgram::Part1->subroutine1();
Run Code Online (Sandbox Code Playgroud)

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

sub new {
    my ($class, @args) = @_;
    ...
    return bless $thing, $class;
}
Run Code Online (Sandbox Code Playgroud)

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

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

这将调用子程序do_something_with与对象作为第一个参数再其次是价值$bar这是你最初传递到第二列表元素method@args.这样对象本身就不会丢失.

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

  • `$ object-> method(@args)`不"只调用Class :: method".它调用继承树中第一个名为`method`的方法. (2认同)

yst*_*sth 5

同时使用!

use Module::Two;

Module::Two::->class_method();
Run Code Online (Sandbox Code Playgroud)

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

Module::Two->class_method();
Run Code Online (Sandbox Code Playgroud)

将被解释为:

Module::Two()->class_method();
Run Code Online (Sandbox Code Playgroud)

(在Module中调用子例程2并尝试在其返回值上调用class_method - 可能导致运行时错误或在某个完全不同的类中调用类或实例方法)如果在模块中碰巧有一个子二 - 这是你的不应该依赖于这种或那种方式,因为它不是您的代码业务中的任何模块.