perl 当'can'函数以这种方式使用时,它意味着什么?

0md85ypi  于 2023-06-30  发布在  Perl
关注(0)|答案(2)|浏览(117)

我知道'can'方法检查包是否有'some_method'方法。但是,“->(animal => $x)”部分发生了什么?

$z = __PACKAGE__->can("some_method")->(animal => $x)
dauxcl2d

dauxcl2d1#

can()将返回对方法的引用(如果它存在),然后方法将被“取消引用箭头”取消引用。你必须把它 Package 到eval中,否则如果“some_method”不存在,就会出现异常。阅读更多内容:
关于can()perldoc UNIVERSAL
关于子程序的取消引用:perldoc perlref

bd1hkmkf

bd1hkmkf2#

can返回方法的代码引用。Perl“方法”只是普通的Perl子例程,它期望类或对象(“invocant”)作为第一个参数。

sub some_method {
    my($self, @args) = @_;
    ...
}

在箭头符号中,调用方在左边,方法在右边:

$object->method();

这实际上是调用调用者包中的子例程,其中调用者成为第一个参数:

SomePackage::method($object)

记住,一个对象仅仅是一个受祝福的引用,这意味着该引用已经被标记了一个包名。我们称之为“对象”,当你调用一个对象上的方法时,它使用这个标签来确定从哪里开始寻找要使用的正确子例程。
不过,这样直接调用它忽略了几个面向对象的特性。例如,您不会使用继承。您直接调用特定的子例程,而不是让Perl找到适当的方法。
回到你的代码。can可以搜索整个继承树,以找到要调用的子例程。它可能不在你开始使用的包中。然后,它返回找到的任何内容的代码引用,但您不知道哪个包提供了该子例程。你也不知道是谁要求的代码引用。
您现在有了代码引用,并且希望调用它。你必须自己提供请求者:

$coderef->(INVOCANT, @args);

有人认为“animal”(一个简单的字符串,这意味着这可能是一个类方法)是正确的调用者。此代码的第一个参数不是对象:

$coderef->('animal', @args);

但是,不要使用这样的代码。几乎没有人这样做,它颠覆了面向对象代码的许多优点。我倾向于这样写:

if (eval { __PACKAGE__->can('some_method')}) {
    __PACKAGE__->some_method(@args);
}

请注意,在这里使用__PACKAGE__也很奇怪(这来自于一个习惯性的滥用者)。我怀疑如果你使用它,有一个更好的方法来完成任务。

相关问题