我正在阅读该attributes
模块的文档,并遇到了一个我从未见过的方法调用符号:
use attributes ();
attributes::->import(__PACKAGE__, \$x, 'Bent');
Run Code Online (Sandbox Code Playgroud)
该文档没有提供此语法的解释。
经调查,它似乎Package::->method()
相当于Package->method()
和'Package'->method()
。
它似乎也相当于Package::method('Package')
,前提是该方法不是继承的。
问题 0:使用Package::->method()
符号有什么实际原因吗?
编辑:我发现如果您有一个与包同名的常量,Package::->method()
则调用包方法,而Package->method()
调用常量上的方法。
use constant Foo => bless {}, 'Bar'; # or just => 'Bar'
print Foo::->method(); # prints 'Foo method'
print 'Foo'->method(); # prints 'Foo method'
print Foo->method(); # prints 'Bar method'
package Foo;
sub method { 'Foo method' }
package Bar;
sub method { 'Bar method' }
Run Code Online (Sandbox Code Playgroud)
奇怪的是use warnings
,这个脚本会给出“Bareword 'Foo::'引用不存在的包”警告,但无论如何都会执行它,这让我更加困惑。
更奇怪的是,Foo::method();
在该Foo::->method()
行之前添加该行可以消除“Bareword”警告。
问题1:有人可以解释一下这是怎么回事吗?
对于后代来说,这是 Perl v5.38.0。
Package::->method
是一种(稍微)更安全的书写方式Package->method
。
文档对此做出了回答。Perl 如何解析未加引号的裸词?也相关。
Foo::
相当于"Foo"
,但它还检查名称空间是否Foo
存在。
Foo
也意味着"Foo"
,但前提是它没有任何其他含义。before 时它不受限制->
,但这里没有什么特别的Foo
。因此,如果您有一个名为 的子程序Foo
,它将调用该子程序。如果您有一个名为 的常量Foo
,则会使用它。
总之,
Foo::->method
总是意味着"Foo"->method
。Foo->method
通常意味着"Foo"->method
.Foo->method
也可能意味着Foo()->method
。由此,我们得出使用 的以下原因Foo::
:
通过使用Foo::
,您可以避免意外调用子程序。(这包括常量。)
在实践中发生这种情况的可能性非常小。人们希望,这可以在测试中找到。但考虑到这种情况的罕见性,一旦发生可能会令人困惑。
通过使用Foo::
,您可以表明这不是子调用。
但当你看到某种形式的东西时,这已经是假设了Foo->method
。当它是子调用时发出信号更为重要(例如,通过使用Foo()->method
)。
通过使用Foo::
,如果您忘记加载模块,您可以获得更好的诊断。
你得到
Bareword "Foo::" refers to nonexistent package at ...
Can't locate object method "method" via package "Foo" (perhaps you forgot to load "Foo"?)` at ...
Run Code Online (Sandbox Code Playgroud)
代替
Can't locate object method "method" via package "Foo" (perhaps you forgot to load "Foo"?)` at ...
Run Code Online (Sandbox Code Playgroud)
我说得更好吗?这对我来说更吵。
归档时间: |
|
查看次数: |
138 次 |
最近记录: |