明确引用类名而不是使用裸字(被视为字符串)是避免语法歧义的三种方法之一。 Foo::->new
的Ginnz on reddit for pointing this out to me部分进行了说明。
举一个简单的例子
my $NUM = "Type::Tiny"->new(
name => "Number",
constraint => sub { looks_like_number($_) },
message => sub { "$_ ain't a number" },
);
在上面的示例中,常数package Foo { sub new { die 7 } };
package Bar { sub new { die 42 } };
sub Foo { "Bar" }
Foo->new();
解析为“ Bar”,因此它调用的是Foo
而不是"Bar"->new
。如何停止解决子程序?您可以引用它。
"Foo"->new
关于性能含义,使用字符串而不是裸字不会使情况恶化。我已经确认"Foo"->new();
生成的optree是相同的。因此,作为一般规则,如果您重视正确性,似乎最好引用Classnames。
这在Perl编程中已提到,(在间接方法调用]的上下文中很遗憾)]
...因此,我们将告诉您,只要有两件事是对的,您几乎总是可以使用一个简单的类名。首先,没有与该类同名的子例程。 (如果遵循
之一O=Deparse
的子例程名称以小写字母开头,而new
的类名称以大写字母开头>>)的约定,则永远不会有问题。第二,在类中加载了ElvenRing
这些声明中的任何一个都确保Perl知道
use ElvenRing; require ElvenRing;
是模块名称,即使您碰巧声明了一个您在当前程序包中的ElvenRing
子例程。而且,这很有意义:仅当您的子例程(通常为小写)与类具有相同的名称(通常为大写)时,才会发生混淆。仅当您违反上述命名约定时,才会发生这种情况。
tldr;如果您知道类名并且重视混乱的正确性,则最好引用类名。
旁注:或者,您可以通过将new
附加到函数的结尾来停止对裸字的解析,例如在上述ElvenRing
中。
感谢new
和::
明确引用类名而不是使用裸字(被视为字符串)是避免语法歧义的三种方法之一。 Foo::->new
的Ginnz on reddit for pointing this out to me部分进行了说明。
因为Perl允许您将裸词用于程序包名称和子例程名称,它有时会解释裸词的含义错误地。例如,构造Toby Inkster for the comment (though it didn't make sense to me on first read).可以是解释为Invoking Class Methods或perlobj documentation。在英语中,第二种解释为“调用名为
Class->new()
的子例程,然后以'Class'->new()
的返回值作为方法调用Class()->new()
。”是当前名称空间中名为Class()
的子例程,Perl将始终将new()
解释为第二种选择:调用Class()
返回的对象上的Class()
。
请参见下面的演示,了解这种奇怪的情况。
,作为方法以两种方式调用名为Class->new()
其输出为
返回伪造假冒的::新的类型::细小::新类型::细小::新类型::微小::新上述文档的其余部分显示了如何防止意外行为或意外错误。
您可以强制Perl使用第一种解释(即
new()
的类。首先,你可以在类名后附加Class()
:#! /usr/bin/env perl use strict; use warnings; sub Type::Tiny { print "Returning Bogus\n" ; return "Bogus" } sub Type::Tiny::new { print "Type::Tiny::new\n" } sub Bogus::new { print "Bogus::new\n" } my $class = "Type::Tiny"; Type::Tiny->new; Type::Tiny::->new; "Type::Tiny"->new; $class->new;
Perl始终将其解释为方法调用。
或者,您可以引用类名:
"Class"
当然,如果类名在标量中,Perl会做对以及:
::
适用于您的问题,以下所有电话均等效。
Class::->new()
明确引用类名而不是使用裸字(被视为字符串)是避免语法歧义的三种方法之一。 Foo::->new
的Ginnz on reddit for pointing this out to me部分进行了说明。