3

new方法Parse::RecDescent有这个原型:

sub new ($$$)
{
   # code goes here
}

如果我创建这样的对象:

my $parser = Parse::RecDescent->new($grammar);

它将创建一个解析器,该方法将接收 2 个参数“Parse::RecDescent”和 $grammar,对吗?如果我尝试创建一个对象,例如:

Parse::RecDescent::new("Parse::RecDescent",$grammar)

这将失败说“Parse::RecDescent::new 的参数不足”,我理解这条消息。我只传递了 2 个参数。但是,我不明白为什么箭头版本有效。

你可以解释吗?

4

1 回答 1

11

当您将其作为 OO 风格的方法调用时,不会检查函数原型。此外,当您使用 & 调用子程序时,您会绕过原型检查,如&sub(arg0, arg1..);

perldoc perlsub

“&”形式不仅使参数列表成为可选的,它还禁止对您提供的参数进行任何原型检查。这部分是出于历史原因,部分是因为如果您知道自己在做什么,就有一种方便的作弊方式。请参阅下面的原型。

方法调用也不受原型影响,因为要调用的函数在编译时是不确定的,因为调用的确切代码取决于继承。

虽然Parse::RecDescent::new("Parse::RecDescent", $grammar)在语法上是正确的,但这是调用构造函数的一种非常糟糕的方式,现在您正在强制它在该类中定义(而不是在祖先中)。如果您确实需要验证您的参数,请在方法内部进行:

sub new
{
    my ($class, @args) = @_;
    die "Not enough arguments passed to constructor" if @args < 2;
    # ...
}

另请参阅早期关于原型的问题以及为什么它们通常不是一个好主意。

于 2010-02-12T22:19:58.183 回答