【发布时间】:2014-04-26 14:18:44
【问题描述】:
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
这段代码甚至不需要被执行,而只是被解析器看到,以便让 Perl 从现在开始将字符串 'Input' 解释为文件句柄。因此,一个方法调用'Input'->awesome 会死掉,因为代表文件句柄的对象没有很棒的方法。
由于我只控制我的类而不控制其他代码,我不能简单地决定只在任何地方使用词法文件句柄。
有什么办法可以强制Input->awesome 始终是Input 包上的方法调用,但绝不是文件句柄(至少在我控制的范围内)?我认为不应该有任何名称冲突,因为 Input 包实际上是 %Input:: stash。
重现问题的完整代码(另见ideone):
use strict;
use warnings;
use feature 'say';
say "This is perl $^V";
package Input {
sub awesome {
say "yay, this works";
}
}
# this works
'Input'->awesome;
# the "open" is parsed, but not actually executed
eval <<'END';
sub red_herring {
open Input, "<&", \*STDIN or die $!;
}
END
say "eval failed: $@" if $@;
# this will die
eval {
'Input'->awesome;
};
say "Caught: $@" if $@;
示例输出:
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.
【问题讨论】:
-
@Zaid 不,
awesome Input的行为与Input->awesome相同。有趣的是,awesome 'Input'无法编译,因为它被视为函数调用。 -
@Zaid:
awesome Class::等价于Class::->awesome。 -
@amon :
awesome Input::似乎也没有强制 Perl 将裸词解释为类名,尽管文档表明:You can force Perl to interpret the bareword as a class name by appending "::" to it -
Input::awesome工作 -
@Zaid 我一般没有这个选项。这与这个问题的目的无关,但我真正的问题集中在
import周围,当我的包是used 时,它将被隐式调用。这非常巧妙地失败了,因为IO::File->import被调用了。
标签: perl filehandle method-call