为什么此代码的两个版本都没有通过 -c Perl 检查?

发布于 2024-08-21 22:46:02 字数 491 浏览 5 评论 0原文

Parse::RecDescentnew 方法有这个原型:

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个参数。但是,我不明白为什么箭头版本有效。

你能解释一下吗?

The new method of Parse::RecDescent has this prototype:

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

and if I create an object like this:

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

it will create a parser, and the method will receive 2 parameters "Parse::RecDescent" and $grammar, right? If I try to create an object like:

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

this will fail saying "Not enough arguments for Parse::RecDescent::new", and I understand this message. I'm only passing 2 parameters. However, I don't understand why the arrow version works.

Can you explain?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

一城柳絮吹成雪 2024-08-28 22:46:02

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

From perldoc perlsub

不仅是“&”表单使参数列表可选,它还会禁用对您提供的参数进行任何原型检查。这部分是为了
历史原因,部分原因是如果你知道自己在做什么,就可以方便地作弊。请参阅下面的原型。

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

虽然 Parse::RecDescent::new("Parse::RecDescent", $grammar) 在语法上是正确的,但这是一种调用构造函数的非常难闻的方式,现在您强制将其定义在那个类(而不是祖先)。如果您确实需要验证您的参数,请在方法内执行此操作:

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

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

Function prototypes are not checked when you call it as an OO-style method. In addition, you bypass prototype checking when you call a sub with &, as in &sub(arg0, arg1..);

From perldoc perlsub:

Not only does the "&" form make the argument list optional, it also disables any prototype checking on arguments you do provide. This is partly for
historical reasons, and partly for having a convenient way to cheat if you know what you're doing. See Prototypes below.

Method calls are not influenced by prototypes either, because the function to be called is indeterminate at compile time, since the exact code called depends on inheritance.

While Parse::RecDescent::new("Parse::RecDescent", $grammar) is syntactically correct, that's a pretty smelly way of calling the constructor, and now you are forcing it to be defined in that class (rather than in an ancestor). If you really need to validate your arguments, do it inside the method:

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

See also this earlier question on prototypes and why they aren't usually such a great idea.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文