Perl具有以文件句柄命名的字符串作为文件句柄的功能:
# let this be some nice class I wrote
package Input {
sub 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 :: 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.
解决方法
对于两个不同的东西(一个使用的类和文件句柄)使用相同的标识符就会出现问题.如果您的类是从使用文件句柄的代码中使用的另一个类使用的,那么该错误不会出现:
My1.pm
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;