为什么某些用户在Perl中引用类名?

问题描述 投票:8回答:2

[看Type::Tiny,我看到对Type::Tiny的调用中的类名在官方文档中被引用,

Type::Tiny->new

为什么?这仅仅是样式吗?这种做法是否会对性能产生影响?

perl coding-style classname bareword
2个回答
7
投票

举一个简单的例子

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::->newGinnz 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 Methodsperlobj 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()

0
投票

明确引用类名而不是使用裸字(被视为字符串)是避免语法歧义的三种方法之一。 Foo::->newGinnz on reddit for pointing this out to me部分进行了说明。

© www.soinside.com 2019 - 2024. All rights reserved.