0

我看到__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
4

3 回答 3

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' })->();
于 2013-04-23T06:28:41.860 回答
3

您似乎误解了 when__PACKAGE__被视为特殊文字

The special literals only have their special meaning when they are a "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

There are a few ways to get around this:

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}->();

Really there is very rarely a good reason to use __PACKAGE__.

于 2013-04-24T17:18:46.397 回答
0

在包(包括 in )中搜索函数(可能是方法)的规范方法__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")'

做你所期望的。

于 2013-04-24T12:55:08.333 回答