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::
.
Полный код для воспроизведения проблемы (см. также 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: [email protected]" if [email protected];
# this will die
eval {
'Input'->awesome;
};
say "Caught: [email protected]" if [email protected];
Пример вывода:
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.