我看到__PACKAGE__
将被编译为包名。
为什么代码:
Foo::bar()
可以工作。但代码:
__PACKAGE__::bar()
会产生错误:
Undefined subroutine &__PACAKGE__::bar called
调用者在Foo包中,所以__PACKAGE__
将是Foo;
希望你能解释一下:)
让我添加一个例子来解释这个场景:
$ perl -e 'package Foo ; sub bar { print "hello\n" } ; __PACKAGE__::bar()'
Undefined subroutine &__PACKAGE__::bar called at -e line 1.
$ perl -e 'package Foo ; sub bar { print "hello\n" } ; Foo::bar()'
hello
答案 0 :(得分:4)
你似乎错了。 Foo::bar()
和__PACKAGE__::bar()
的工作方式完全相同。
$ perl -e'sub Foo { "main" } Foo::bar()'
Undefined subroutine &Foo::bar called at -e line 1.
$ perl -e'__PACKAGE__::bar()'
Undefined subroutine &__PACKAGE__::bar called at -e line 1.
和
$ perl -E'package Foo; sub bar { say "hello" } Foo::bar()'
hello
$ perl -E'package __PACKAGE__; sub bar { say "hello" } __PACKAGE__::bar()'
hello
他们都在指定的包(bar
和Foo
)中调用__PACKAGE__
。 Foo
和__PACKAGE__
都不被视为函数调用。
这是因为Foo
和__PACKAGE__
都不是代码中的单词。如果您想从bar
返回的包中调用__PACKAGE__
,可以使用
bar()
如果你有一个包含任意包的var(可能从__PACKAGE__
获得),你可以使用
(\&{ $pkg . '::bar' })->();
答案 1 :(得分:3)
您似乎误解了__PACKAGE__
被视为special literal的时间。
special literals只有"separate token"才具有特殊含义。
use 5.10.0;
use strict;
use warnings;
say 'in package: ', __PACKAGE__;
sub bar{ say 'this is the one you might be expecting' }
__PACKAGE__::bar(); # not a separate token
{
package __PACKAGE__;
sub bar{ say 'this is the one you actually get' }
}
in package: main
this is the one you actually get
有几种方法可以解决这个问题:
bar(); # recommended
{
no strict 'refs';
*{__PACKAGE__.'::bar'}->(); # symbol ref
${__PACKAGE__.'::'}{bar}->(); # magical %package:: variable
}
__PACKAGE__->can('bar')->(); # may get 'bar' from a parent package
__PACKAGE__->bar(); # same as __PACKAGE__->can('bar')->(__PACKAGE__)
our $symbol_table = do{ no strict 'refs'; \%{__PACKAGE__.'::'} };
$symbol_table->{bar}->();
真的很少有理由使用__PACKAGE__
。
答案 2 :(得分:0)
在包(包括__PACKAGE__
)中搜索函数(可能是方法)的规范方法是使用can
方法。在类名或实例上调用时,它返回对函数/方法的引用;然后你可以取消引用它来调用实际的函数。在你的情况下,这可以是
perl -E 'sub bar { say "hello" } __PACKAGE__->can("bar")->()'
这与Michael Prz在评论中建议的区别在于第一个论点的处理。例如,当您尝试
时perl -E 'sub bar { say "hello " . shift } __PACKAGE__->bar("name")'
你得到了
hello main
因为main是调用参数。然而
perl -E 'sub bar { say "hello " . shift } __PACKAGE__->can("bar")->("name")'
做你期望的事。