防止将字符串解释为文件句柄 [英] Prevent strings from being interpreted as a file handle
问题描述
Perl具有将名为文件句柄的字符串用作 文件句柄的功能:
Perl has the feature that strings named like a file handle are taken to be a filehandle:
# let this be some nice class I wrote
package Input {
sub awesome { ... }
}
因此,当我们执行Input->awesome
或格外小心时:'Input'->awesome
,该方法将被调用.除非:
So when we do Input->awesome
or extra-careful: 'Input'->awesome
, the method will get called. Unless:
# now somewhere far, far away, in package main, somebody does this:
open Input, "<&", \*STDIN or die $!; # normally we'd open to a file
甚至不必执行此代码,而只是为了使Perl从现在开始使Perl将字符串'Input'
解释为文件句柄,解析器才能看到.因此,方法调用'Input'->awesome
将死亡,因为代表文件句柄的对象没有很棒的方法.
This code doesn't even have to be executed, but only be seen by the parser in order to have Perl interpret the string 'Input'
as a file handle from now on. Therefore, a method call 'Input'->awesome
will die because the object representing the file handle doesn't have awesome methods.
由于我只能控制类,而不能控制其他代码,所以我不能简单地决定只在各处使用词法文件句柄.
As I am only in control of my class but not of other code, I can't simply decide to only use lexical filehandles everywhere.
有什么办法可以强制Input->awesome
始终是Input
程序包上的方法调用,但从来没有文件句柄(至少在我控制的范围内)?我认为不应有任何名称冲突,因为Input
包实际上是%Input::
藏匿处.
Is there any way I can force Input->awesome
to always be a method call on the Input
package, but never a file handle (at least in scopes controlled by me)? I'd think there shouldn't be any name clash because the Input
package is actually the %Input::
stash.
重现该问题的完整代码(另请参见此 ideone ):
Full code to reproduce the problem (see also this 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.
推荐答案
对于两个不同的事物(使用的类和文件句柄)使用相同的标识符会引起问题.如果您的类是从使用文件句柄的代码中使用的其他类中使用的,则不会出现该错误:
Using the same identifier for two different things (a used class and filehandle) begs for problems. If your class is used from a different class that's used in the code that uses the filehandle, the error does not appear:
package My1;
use warnings;
use strict;
sub new { bless [], shift }
sub awesome { 'My1'->new }
__PACKAGE__
My2.pm
package My2;
use warnings;
use strict;
use parent 'My1';
sub try {
my $self = shift;
return ('My1'->awesome, $self->awesome);
}
__PACKAGE__
script.pl
#!/usr/bin/perl
use warnings;
use strict;
use My2;
open My1, '<&', *STDIN;
my $o = 'My2'->new;
print $o->awesome, $o->try;
这篇关于防止将字符串解释为文件句柄的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!