📄 ch10_02.htm
字号:
<html><head><title>Autoloading (Programming Perl)</title><!-- STYLESHEET --><link rel="stylesheet" type="text/css" href="../style/style1.css"><!-- METADATA --><!--Dublin Core Metadata--><meta name="DC.Creator" content=""><meta name="DC.Date" content=""><meta name="DC.Format" content="text/xml" scheme="MIME"><meta name="DC.Generator" content="XSLT stylesheet, xt by James Clark"><meta name="DC.Identifier" content=""><meta name="DC.Language" content="en-US"><meta name="DC.Publisher" content="O'Reilly & Associates, Inc."><meta name="DC.Source" content="" scheme="ISBN"><meta name="DC.Subject.Keyword" content=""><meta name="DC.Title" content="Autoloading"><meta name="DC.Type" content="Text.Monograph"></head><body><!-- START OF BODY --><!-- TOP BANNER --><img src="gifs/smbanner.gif" usemap="#banner-map" border="0" alt="Book Home"><map name="banner-map"><AREA SHAPE="RECT" COORDS="0,0,466,71" HREF="index.htm" ALT="Programming Perl"><AREA SHAPE="RECT" COORDS="467,0,514,18" HREF="jobjects/fsearch.htm" ALT="Search this book"></map><!-- TOP NAV BAR --><div class="navbar"><table width="515" border="0"><tr><td align="left" valign="top" width="172"><a href="ch10_01.htm"><img src="../gifs/txtpreva.gif" alt="Previous" border="0"></a></td><td align="center" valign="top" width="171"><a href="ch10_01.htm">Chapter 10: Packages</a></td><td align="right" valign="top" width="172"><a href="ch11_01.htm"><img src="../gifs/txtnexta.gif" alt="Next" border="0"></a></td></tr></table></div><hr width="515" align="left"><!-- SECTION BODY --><h2 class="sect1">10.2. Autoloading</h2><p><a name="INDEX-2247"></a><a name="INDEX-2248"></a><a name="INDEX-2249"></a><a name="INDEX-2250"></a><a name="INDEX-2251"></a><a name="INDEX-2252"></a>Normally, you can't call a subroutine that isn't defined. However, ifthere is a subroutine named <tt class="literal">AUTOLOAD</tt> in theundefined subroutine's package (or in the case of an object method, inthe package of any of the object's base classes), then the<tt class="literal">AUTOLOAD</tt> subroutine is called with the samearguments that would have been passed to the original subroutine. Youcan define the <tt class="literal">AUTOLOAD</tt> subroutine to return valuesjust like a regular subroutine, or you can make it define the routinethat didn't exist and then call that as if it'd been there all along.</p><p>The fully qualified name of the original subroutine magically appearsin the package-global <tt class="literal">$AUTOLOAD</tt> variable, in thesame package as the <tt class="literal">AUTOLOAD</tt> routine. Here's asimple example that gently warns you about undefined subroutineinvocations instead of exiting:<blockquote><pre class="programlisting">sub AUTOLOAD { our $AUTOLOAD; warn "Attempt to call $AUTOLOAD failed.\n";}blarg(10); # our $AUTOLOAD will be set to main::blargprint "Still alive!\n";</pre></blockquote>Or you can return a value on behalf of the undefined subroutine:<blockquote><pre class="programlisting">sub AUTOLOAD { our $AUTOLOAD; return "I see $AUTOLOAD(@_)\n";}print blarg(20); # prints: I see main::blarg(20)</pre></blockquote><a name="INDEX-2253"></a><a name="INDEX-2254"></a><a name="INDEX-2255"></a>Your <tt class="literal">AUTOLOAD</tt> subroutine might load a definitionfor the undefined subroutine using <tt class="literal">eval</tt> or<tt class="literal">require</tt>, or use the glob assignment trick discussedearlier, and then execute that subroutine using the special form of<tt class="literal">goto</tt> that can erase the stack frame of the<tt class="literal">AUTOLOAD</tt> routine without a trace. Here we definethe subroutine by assigning a closure to the glob:<blockquote><pre class="programlisting">sub AUTOLOAD { my $name = our $AUTOLOAD; *$AUTOLOAD = sub { print "I see $name(@_)\n" }; goto &$AUTOLOAD; # Restart the new routine.}blarg(30); # prints: I see main::blarg(30)glarb(40); # prints: I see main::glarb(40)blarg(50); # prints: I see main::blarg(50)</pre></blockquote><a name="INDEX-2256"></a><a name="INDEX-2257"></a><a name="INDEX-2258"></a><a name="INDEX-2259"></a><a name="INDEX-2260"></a><a name="INDEX-2261"></a><a name="INDEX-2262"></a>The standard <tt class="literal">AutoSplit</tt> module is used by module writers to split their modules into separate files (with filenames ending in <em class="emphasis">.al</em>), each holding one routine. Thefiles are placed in the <em class="emphasis">auto/</em> directory of yoursystem's Perl library, after which the files can be autoloaded ondemand by the standard <tt class="literal">AutoLoader</tt> module.</p><p>A similar approach is taken by the <tt class="literal">SelfLoader</tt>module, except that it autoloads functions from the file's own<tt class="literal">DATA</tt> area, which is less efficient in some ways andmore efficient in others. Autoloading of Perl functions by<tt class="literal">AutoLoader</tt> and <tt class="literal">SelfLoader</tt> isanalogous to dynamic loading of compiled C functions by<tt class="literal">DynaLoader</tt>, except that autoloading is done at thegranularity of the function call, whereas dynamic loading is done atthe granularity of the complete module, and will usually link in manyC or C++ functions all at once. (Note that many Perl programmers getalong just fine without the <tt class="literal">AutoSplit</tt>,<tt class="literal">AutoLoader</tt>, <tt class="literal">SelfLoader</tt>, or<tt class="literal">DynaLoader</tt> modules. You just need to know thatthey're there, in case you <em class="emphasis">can't</em> get along justfine without them.) <a name="INDEX-2263"></a></p><p>One can have great fun with <tt class="literal">AUTOLOAD</tt> routines that serve as wrappersto other interfaces. For example, let's pretend that any function thatisn't defined should just call <tt class="literal">system</tt> with its arguments. All you'ddo is this:<blockquote><pre class="programlisting">sub AUTOLOAD { my $program = our $AUTOLOAD; $program =~ s/.*:://; # trim package name system($program, @_);}</pre></blockquote>(Congratulations, you've now implemented a rudimentary form of the<tt class="literal">Shell</tt> module that comes standard with Perl.) You can call yourautoloader (on Unix) like this:<blockquote><pre class="programlisting">date();who('am', 'i');ls('-l');echo("Abadugabudabuda...");</pre></blockquote>In fact, if you predeclare the functions you want to call that way,you can pretend they're built-ins and omit the parentheses on the call:<blockquote><pre class="programlisting">sub date (;$$); # Allow zero to two arguments.sub who (;$$$$); # Allow zero to four args.sub ls; # Allow any number of args.sub echo ($@); # Allow at least one arg.date;who "am", "i";ls "-l";echo "That's all, folks!";</pre></blockquote></p><a name="INDEX-2264"></a><a name="INDEX-2265"></a><a name="INDEX-2266"></a><!-- BOTTOM NAV BAR --><hr width="515" align="left"><div class="navbar"><table width="515" border="0"><tr><td align="left" valign="top" width="172"><a href="ch10_01.htm"><img src="../gifs/txtpreva.gif" alt="Previous" border="0"></a></td><td align="center" valign="top" width="171"><a href="index.htm"><img src="../gifs/txthome.gif" alt="Home" border="0"></a></td><td align="right" valign="top" width="172"><a href="ch11_01.htm"><img src="../gifs/txtnexta.gif" alt="Next" border="0"></a></td></tr><tr><td align="left" valign="top" width="172">10.1. Symbol Tables</td><td align="center" valign="top" width="171"><a href="index/index.htm"><img src="../gifs/index.gif" alt="Book Index" border="0"></a></td><td align="right" valign="top" width="172">11. Modules</td></tr></table></div><hr width="515" align="left"><!-- LIBRARY NAV BAR --><img src="../gifs/smnavbar.gif" usemap="#library-map" border="0" alt="Library Navigation Links"><p><font size="-1"><a href="copyrght.htm">Copyright © 2001</a> O'Reilly & Associates. All rights reserved.</font></p><map name="library-map"> <area shape="rect" coords="2,-1,79,99" href="../index.htm"><area shape="rect" coords="84,1,157,108" href="../perlnut/index.htm"><area shape="rect" coords="162,2,248,125" href="../prog/index.htm"><area shape="rect" coords="253,2,326,130" href="../advprog/index.htm"><area shape="rect" coords="332,1,407,112" href="../cookbook/index.htm"><area shape="rect" coords="414,2,523,103" href="../sysadmin/index.htm"></map><!-- END OF BODY --></body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -