Por que as duas versões deste código não estão falhando na verificação -c perl?
-
20-09-2019 - |
Pergunta
o new
método de Parse::RecDescent
tem este protótipo:
sub new ($$$)
{
# code goes here
}
E se eu criar um objeto como este:
my $parser = Parse::RecDescent->new($grammar);
Ele criará um analisador e o método receberá 2 parâmetros "Parse :: RecDescent" e $ Grammar, certo? Se eu tentar criar um objeto como:
Parse::RecDescent::new("Parse::RecDescent",$grammar)
Isso falhará dizendo "argumentos insuficientes para analisar :: Recdescent :: New", e eu entendo esta mensagem. Estou apenas passando 2 parâmetros. No entanto, não entendo por que a versão de seta funciona.
Você pode explicar?
Solução
Os protótipos de função não são verificados quando você o chama de método de estilo OO. Além disso, você ignora a verificação de protótipos quando liga para um sub &, como em &sub(arg0, arg1..);
A partir de Perldoc Perlsub:
O formulário "&" não apenas torna a lista de argumentos opcional, como também desativa qualquer protótipo de verificação dos argumentos que você fornece. Isso é parcialmente por razões históricas e em parte por ter uma maneira conveniente de trapacear se você souber o que está fazendo. Veja protótipos abaixo.
As chamadas de método também não são influenciadas por protótipos, porque a função a ser chamada é indeterminada no tempo de compilação, uma vez que o código exato chamado depende da herança.
Enquanto Parse::RecDescent::new("Parse::RecDescent", $grammar)
é sintaticamente correto, essa é uma maneira bastante fedorenta de chamar o construtor, e agora você está forçando a ser definido nessa classe (e não em um ancestral). Se você realmente precisar validar seus argumentos, faça -o dentro do método:
sub new
{
my ($class, @args) = @_;
die "Not enough arguments passed to constructor" if @args < 2;
# ...
}
Veja também Esta pergunta anterior sobre protótipos E por que eles geralmente não são uma ótima idéia.