标题几乎总结了它,但无论如何这里是长版本。
在发布一小段perl代码后,我被告知要避免使用间接对象表示法,因为它有几个副作用"。评论引用了这一特定的一行:
my $some_object = new Some::Module(FIELD => 'value');
因为这就是我一直以来的做法,为了与时俱进,我因此要求:
我正打算问这位评论者,但对我而言,这是值得发表的。
答案 0 :(得分:18)
主要问题是它含糊不清。确实
my $some_object = new Some::Module(FIELD => 'value');
意味着调用new
包中的Some::Module
方法,或者是否意味着调用当前包中的new
函数,调用Module
的结果具有给定参数的Some
包中的函数?
即,它可以解析为:
# method call
my $some_object = Some::Module->new(FIELD => 'value');
# or function call
my $some_object = new(Some::Module(FIELD => 'value'));
另一种方法是使用显式方法调用符号Some::Module->new(...)
。
通常情况下,解析器会正确猜测,但最佳做法是避免歧义。
答案 1 :(得分:9)
它有什么坏处?
间接方法表示法的问题是可以避免的,但是告诉人们避免使用间接方法表示法要容易得多。
主要问题是很容易意外地调用错误的功能。请使用以下代码,例如:
package Widget;
sub new { ... }
sub foo { ... }
sub bar { ... }
sub method {
...;
my $o = new SubWidget;
...;
}
1;
在该代码中,new SubWidget
预计意味着
SubWidget->new()
相反,它实际上意味着
new("SubWidget")
那就是说,使用strict会捕获这个错误的大部分实例。如果要将use strict;
添加到上面的代码段,则会产生以下错误:
Bareword "SubWidget" not allowed while "strict subs" in use at Widget.pm line 11.
也就是说,有些情况下使用strict不会捕获错误。它们主要涉及在方法调用的参数周围使用parens(例如new SubWidget($x)
)。
这意味着
前者是可以忍受的,而后者是可以避免的。但是,与其告诉人们避免使用间接方法表示法#34;围绕方法调用的参数使用parens,我们只是告诉人们"避免使用间接方法表示法"。它太脆弱了。
还有另一个问题。它不只是使用间接对象表示法是一个问题,它在Perl中支持它。该特征的存在导致多个问题。首先,
从好的方面来说,使用no indirect;
可以解决第一个问题。
如何重写该行?
编写方法调用的正确方法如下:
my $some_object = Some::Module->new(FIELD => 'value');
尽管如此,即使这种语法也不明确。它将首先检查名为Some::Module
的函数是否存在。但是,很少有人能够保护自己免受此类问题的影响。如果您想保护自己,可以使用以下内容:
my $some_object = Some::Module::->new(FIELD => 'value');
答案 2 :(得分:6)
答案 3 :(得分:4)
评论者只是想看Some::Module->new(FIELD => 'value');
作为构造函数。
Perl可以使用indirect object syntax for other bare words that look like they might be methods,但现在perlobj
文档建议不要使用它。
它的一般问题是以这种方式编写的代码是不明确的,并且运用Perl的解析器来测试命名空间,例如:检查编写method Namespace
时是否存在Namespace :: method。