perl - new SomeModule::SomeName vs SomeModule::SomeName->new(),有什么区别?
问题描述
我对 perl 很陌生,所以你必须原谅我的无知。
我正在做一个遗留项目。我没有专用的 IDE,我使用的是带有专用 Perl 插件的 PHPStorm。将鼠标悬停在new
关键字上时,我收到警告Using of fancy calls is not recommended, use TCO::AEMAP->new()
。
有问题的代码是
my $aemapper = new TCO::AEMAP();
基本上它建议做
my $aemapper = TCO::AEMAP->new();
这种说法有什么优点,还是仅仅是一种约定?我在谷歌上找不到很多东西,因为我不确定要找什么。
解决方案
该new Foo
版本称为间接对象语法。这是在包上调用构造函数的老式方式,在现代 Perl 中不鼓励这样做。这是perldoc 中相关部分的部分引用。
出于多种原因,我们建议您避免使用此语法。
首先,阅读起来可能会令人困惑。在上面的示例中,尚不清楚 save 是由 File 类提供的方法,还是只是一个期望文件对象作为其第一个参数的子例程。
当与类方法一起使用时,问题更加严重。因为 Perl 允许将子例程名称写成裸字,所以 Perl 必须猜测方法后面的裸字是类名还是子例程名。换句话说,Perl 可以将语法解析为 File->new( $path, $data ) 或 new( File( $path, $data ) ) 。
为了解析这段代码,Perl 使用启发式算法,基于它所看到的包名、当前包中存在的子例程、之前看到的裸词以及其他输入。不用说,启发式可以产生非常令人惊讶的结果!
较早的文档(和一些 CPAN 模块)鼓励使用这种语法,特别是对于构造函数,因此您可能仍然会在野外找到它。但是,我们鼓励您避免在新代码中使用它。
另一种方法是在带有箭头的包上new
作为类方法调用,如Foo->new
. 箭头->
做了三件事:
- 它查找左侧的内容。在这种情况下,bareword
Foo
看起来像一个包名。因此 Perl 将查看它是否知道具有该名称的包(或命名空间)。 - 它调用刚刚找到的包中箭头右侧的方法。
- 它传入右边的东西,在我们的例子中是
Foo
包名,作为第一个参数。这就是为什么在方法声明中您会看到my ($class, @args) = @_
或类似的原因。
对于所有其他面向对象的调用,通常使用箭头语法。但是周围有很多使用间接对象语法的旧代码new
,尤其是 CPAN 上的旧模块仍然在其文档中使用它。
两者都有效,但不鼓励使用间接对象语法。用于Foo->new
新代码。
推荐阅读
- php - 从 href 链接获取电子邮件地址
- prometheus - Prometheus 批量导入
- python-3.x - Pytest:没有运行测试
- ruby-on-rails - 如何解决 Rails 表单中的多个nested_resources?
- amazon-web-services - 如何从 AmazonSNSClient 中删除弃用?
- java - 使用集合和列表读取文本文件并删除单词
- mysql - 如何在 JOIN 的 ON 子句上创建动态列?
- calculator - 二次方程输出不正确
- android - 如何使用 Google App Signing 证书生成 .keystore 文件?
- node.js - Nodejs express:如何使用不同路由逻辑所需的常用功能