正常情况下,不能调用一个尚未定义的子例程.
不过,如果在包中定义有一个名为AUTOLOAD的子例程,那么调用这个AUTOLOAD子例程时会为它提供传入原子例程的同样的参数,也就是perl会把对未定义的子例程的调用全部转到AUTOLOAD上来.
在AUTOLOAD中,可以定义返回值,也可以定义不存在的子例程,然后调用该子例程,就像这个子例程本来就存在一样.
使用AUTOLOAD需要理解下面的几点:
- 原子例程的完全限定名(标识符前带包名和冒号)会出现在全局变量$AUTOLOAD中,与AUTOLOAD例程在同一个包中.
- 在AUTOLOAD子例程中使用
eval
或团赋值
方式定义未定义的子例程.( 一分钟了解eval 理解类型团 ) - 使用
goto &NAME
的跳入到AUTOLOAD定义的子例程. - 一旦子例程通过AUTOLOAD被定义,该子例程会保存在符号表中,可供再次调用.
代码展示
#!/usr/bin/perl
use warnings;
use strict;
sub AUTOLOAD{
our $AUTOLOAD;
warn "attempt to call $AUTOLOAD\n";
(my $method = $AUTOLOAD) =~ s/.*:://;
if($method eq 'brag') {
# no strict "refs";
# *$method = sub { ## 团赋值匿名子例程
# print shift;
# print "ok\n";
# };
eval q{ sub brag {my $n = shift; print "brag $n \n";} ## eval定义子例程
goto &brag;
}
}
&brag(20);
&brag(30);
如上代码输出结果
attempt to call main::brag ## 第一次程序进入AUTOLOAD
brag 20 ## goto语句执行的结果
brag 30 ## 第二次调用brag正常执行子例程