Perl 防止字符串被解释为文件句柄

Perl 防止字符串被解释为文件句柄,perl,filehandle,method-call,Perl,Filehandle,Method Call,Perl的一个特性是,类似文件句柄的字符串被视为文件句柄: # let this be some nice class I wrote package Input { sub awesome { ... } } 因此,当我们执行Input->awesome或格外小心:'Input'->awesome时,将调用该方法。除非: # now somewhere far, far away, in package main, somebody does this: open Input, "&

Perl的一个特性是,类似文件句柄的字符串被视为文件句柄:

# let this be some nice class I wrote
package Input {
    sub awesome { ... }
}
因此,当我们执行
Input->awesome
或格外小心:
'Input'->awesome
时,将调用该方法。除非:

# now somewhere far, far away, in package main, somebody does this:
open Input, "<&", \*STDIN or die $!;  # normally we'd open to a file
示例输出:

This is perl v5.16.2
yay, this works
Caught: Can't locate object method "awesome" via package "IO::File" at prog.pl line 27.

将同一标识符用于两个不同的对象(使用过的类和文件句柄)会导致问题。如果您的类来自使用filehandle的代码中使用的其他类,则不会出现错误:

下午1:00 下午2:00 script.pl
#/usr/bin/perl
使用警告;
严格使用;
使用My2;

打开My1,使用裸字
输入作为文件句柄违反了命名约定,即
文件句柄
s只使用大写裸字,而
es和
s只使用大写/驼峰格式的裸字

此外,很久以前就已经引入并鼓励lexcial
$filehandles

因此,使用您的类的程序员显然行为不端,而且由于名称空间是按定义全局的,因此Perl很难解决这一问题(支持chorobas关于乞求问题的声明)

某些命名约定对于所有(动态)语言都至关重要

不过,感谢您提出了这个有趣的问题,这是我第一次在中看到Perl问题,因此我更希望在上看到:)


更新:这里的讨论已经深化:

@Zaid no,
awesome Input
的行为与
Input->awesome
相同。有趣的是,
awesome'Input'
并没有编译,因为它被当作一个函数调用。@Zaid:
awesome类::
相当于
Class::->awesome
@amon:,
awesome输入::
似乎也没有强迫Perl将单词解释为类名,尽管文档中指出:
您可以强制Perl将裸字解释为类名,方法是在其后面附加“:”
Input::awesome
works@Zaid我通常没有这个选择。这与本问题的目的无关,但我真正的问题集中在
import
上,当我的包是
use
d时,它将被隐式调用。这非常微妙地失败了,因为调用了
IO::File->import
。使用两个单独的包(它们甚至不必是单独的文件)可以很好地工作,前提是文件句柄名称是普通的,而不是像
\uu
文件句柄那样的超全局的,我们不会做像
main::My1->awesome
这样的事情,它应该可以工作,但会再次解析为文件句柄。尽管您可能能够运行一个检查,以确定bareword是否已经严重过载并抛出一个错误。当您使用模块时,源代码在调用调用方的上下文中是
eval
ed,甚至在调用
import
之前,您可能会在那里运行这样的检查(在打包之前)。啊,我完全同意您的风格建议。但我问题中的代码只是为了说明问题,而我真正的代码做了更糟糕的事情来引发问题。(我试图让BoabeTebug <代码>使用< <代码>——因为哪位病人甚至会考虑这样做,如果有人以前做过<代码> -E < /COD>,这是不起作用的。我想今天晚些时候我会在修道院发布一个更新版本。当然,如果你想
使用
引爆,最好的办法就是不要在你的@INC中有任何名为
.pm
的文件?
This is perl v5.16.2
yay, this works
Caught: Can't locate object method "awesome" via package "IO::File" at prog.pl line 27.
package My1;

use warnings;
use strict;

sub new { bless [], shift }
sub awesome { 'My1'->new }

__PACKAGE__
package My2;

use warnings;
use strict;
use parent 'My1';

sub try {
    my $self = shift;
    return ('My1'->awesome, $self->awesome);
}

__PACKAGE__
#!/usr/bin/perl
use warnings;
use strict;

use My2;
open My1, '<&', *STDIN;
my $o = 'My2'->new;
print $o->awesome, $o->try;