⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch12_05.htm

📁 编程珍珠,里面很多好用的代码,大家可以参考学习呵呵,
💻 HTM
📖 第 1 页 / 共 3 页
字号:
We use the <tt class="literal">%seen</tt> hash to keep track of which subroutines we'vealready called, so we can avoid calling the same subroutine more thanonce.  This could happen if several parent classes shared a commonancestor.</p><p>Methods that would trigger an <tt class="literal">AUTOLOAD</tt> (described in the next section) willnot be accurately reported unless the package has declared (but notdefined) the subroutines it wishes to have autoloaded.</p></dd><dt><b><em class="replaceable">INVOCANT</em><tt class="literal">-&gt;VERSION(</tt><em class="replaceable">NEED</em><tt class="literal">)</tt></b></dt><dd><p><a name="INDEX-2478"></a><a name="INDEX-2479"></a>The <tt class="literal">VERSION</tt> method returns the version number of<em class="replaceable">INVOCANT</em>'s class, as stored in thepackage's <tt class="literal">$VERSION</tt> variable.  If the<em class="replaceable">NEED</em> argument is provided, it verifies thatthe current version isn't less than <em class="replaceable">NEED</em>and raises an exception if it is.  This is the method that<tt class="literal">use</tt> invokes to determine whether a module issufficiently recent.<blockquote><pre class="programlisting">use Thread 1.0;   # calls Thread-&gt;VERSION(1.0)print "Running version ", Thread-&gt;VERSION, " of Thread.\n";</pre></blockquote>You may supply your own <tt class="literal">VERSION</tt> method to override the method in<tt class="literal">UNIVERSAL</tt>.  However, this will cause any classes derived from your class to use the overridden method, too. If you don't want that to happen, youshould design your method to delegate other classes' version requestsback up to <tt class="literal">UNIVERSAL</tt>.</p></dd></dl><p>The methods in <tt class="literal">UNIVERSAL</tt> are built-in Perl subroutines, which youmay call if you fully qualify them and pass two arguments, as in<tt class="literal">UNIVERSAL::isa($formobj, "HASH")</tt>.  (This is not recommended,though, because <tt class="literal">can</tt> usually has the answer you're really looking for.)</p><p><a name="INDEX-2480"></a><a name="INDEX-2481"></a>You're free to add your own methods to class<tt class="literal">UNIVERSAL</tt>.  (You should be careful, of course; youcould really mess someone up who is expecting <em class="emphasis">not</em>to find the method name you're defining, perhaps so that they canautoload it from somewhere else.)  Here we create a<tt class="literal">copy</tt> method that objects of all classes can use ifthey've not defined their own.  (We fail spectacularly if invoked on aclass instead of an object.)<blockquote><pre class="programlisting">use Data::Dumper;   use Carp;sub UNIVERSAL::copy {    my $self = shift;    if (ref $self) {        return eval Dumper($self);  # no CODE refs    } else {        confess "UNIVERSAL::copy can't copy class $self";    }}</pre></blockquote> This <tt class="literal">Data::Dumper</tt> strategy doesn'twork if the object contains any references to subroutines, becausethey cannot be properly reproduced.  Even if the source wereavailable, the lexical bindings would be lost.</p><a name="INDEX-2482"></a><a name="INDEX-2483"></a><h3 class="sect2">12.5.4. Method Autoloading</h3><a name="INDEX-2484"></a><a name="INDEX-2485"></a><a name="INDEX-2486"></a><a name="INDEX-2487"></a><a name="INDEX-2488"></a><p><a name="INDEX-2489"></a>Normally, when you call an undefined subroutine in a package thatdefines an <tt class="literal">AUTOLOAD</tt> subroutine, the<tt class="literal">AUTOLOAD</tt> subroutine is called in lieu of raising anexception (see the section <a href="ch10_02.htm#ch10-sect-auto">Section 12.2, "Autoloading"</a> in <a href="ch10_01.htm">Chapter 10, "Packages"</a>).  With methods, this works a littledifferently.  If the regular method search (through the class, itsancestors, and finally <tt class="literal">UNIVERSAL</tt>) fails to find amatch, the same sequence is run again, this time looking for an<tt class="literal">AUTOLOAD</tt> subroutine.  If found, this subroutine iscalled as a method, with the package's <tt class="literal">$AUTOLOAD</tt>variable set to the fully qualified name of the subroutine on whosebehalf <tt class="literal">AUTOLOAD</tt> was called.</p><p>You need to be a bit cautious when autoloading methods.  First, the<tt class="literal">AUTOLOAD</tt> subroutine should return immediately ifit's being called on behalf of a method named<tt class="literal">DESTROY</tt>, unless your goal was to simulate<tt class="literal">DESTROY</tt>, which has a special meaning to Perldescribed in the section <a href="ch12_06.htm#ch10-sect-destruct">Section 12.6, "Instance Destructors"</a> later in this chapter.<blockquote><pre class="programlisting">sub AUTOLOAD {    return if our $AUTOLOAD =~ /::DESTROY$/;    ...}</pre></blockquote>Second, if the class is providing an <tt class="literal">AUTOLOAD</tt>safety net, you won't be able to use <tt class="literal">UNIVERAL::can</tt>on a method name to check whether it's safe to invoke. You have tocheck for <tt class="literal">AUTOLOAD</tt> separately:<blockquote><pre class="programlisting">if ($obj-&gt;can("methname") || $obj-&gt;can("AUTOLOAD")) {    $obj-&gt;methname();}</pre></blockquote>Finally, under multiple inheritance, if a class inherits from two ormore classes each of which has an <tt class="literal">AUTOLOAD</tt>, onlythe leftmost will ever be triggered, since Perl stops as soon as itfinds the first <tt class="literal">AUTOLOAD</tt>.<a name="INDEX-2490"></a></p><p><a name="INDEX-2491"></a><a name="INDEX-2492"></a>The last two quirks are easily circumvented by declaring thesubroutines in the package whose <tt class="literal">AUTOLOAD</tt> issupposed to manage those methods.  You can do this either withindividual declarations:<blockquote><pre class="programlisting">package Goblin;sub kick;sub bite;sub scratch;</pre></blockquote><a name="INDEX-2493"></a>or with the <tt class="literal">use subs</tt> pragma, which is more convenient if you havemany methods to declare:<blockquote><pre class="programlisting">package Goblin;use subs qw(kick bite scratch);</pre></blockquote>Even though you've only declared these subroutines and not defined them, this is enough for the system to think they're real.  Theyshow up in a <tt class="literal">UNIVERAL::can</tt> check, and, more importantly, they show upin step 2 of the search for a method, which will never progress to step 3,let alone step 4.</p><p>"But, but," you exclaim, "they invoke <tt class="literal">AUTOLOAD</tt>, don't they?"  Well,yes, they do eventually, but the mechanism is different.  Having foundthe method stub via step 2, Perl tries to call it.  When it isdiscovered that the method isn't all it was cracked up to be, the<tt class="literal">AUTOLOAD</tt> method search kicks in again, but this time, it starts itssearch in the class containing the stub, which restricts the methodsearch to that class and its ancestors (and <tt class="literal">UNIVERSAL</tt>).  That's how Perl finds the correct <tt class="literal">AUTOLOAD</tt> to run and knows to ignore <tt class="literal">AUTOLOAD</tt>s fromthe wrong part of the original inheritance tree.</p><a name="ch12-sect-pm"></a><h3 class="sect2">12.5.5. Private Methods</h3><p><a name="INDEX-2494"></a><a name="INDEX-2495"></a><a name="INDEX-2496"></a>There is one way to invoke a method so that Perl ignores inheritancealtogether.  If instead of a literal method name, you specify a simplescalar variable containing a reference to a subroutine, then thesubroutine is called immediately.  In the description of <tt class="literal">UNIVERSAL-&gt;can</tt> in the previous section, the last example invokes all overriddenmethods using the subroutine's reference, not its name.</p><p><a name="INDEX-2497"></a><a name="INDEX-2498"></a>An intriguing aspect of this behavior is that it can be used toimplement private method calls.  If you put your class in a module,you can make use of the file's lexical scope for privacy.  First,store an anonymous subroutine in a file-scoped lexical:<blockquote><pre class="programlisting"># declare private methodmy $secret_door = sub {    my $self = shift;    ...};</pre></blockquote>Later on in the file, you can use that variable as though it held amethod name.  The closure will be called directly, without regard toinheritance.  As with any other method, the invocant is passed as anextra argument.<blockquote><pre class="programlisting">sub knock {    my $self = shift;    if ($self-&gt;{knocked}++ &gt; 5) {        $self-&gt;$secret_door();    }}</pre></blockquote>This enables the file's own subroutines (the class methods) to invokea method that code outside that lexical scope cannot access.</p><a name="INDEX-2499"></a><a name="INDEX-2500"></a><a name="INDEX-2501"></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="ch12_04.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="ch12_06.htm"><img src="../gifs/txtnexta.gif" alt="Next" border="0"></a></td></tr><tr><td align="left" valign="top" width="172">12.4. Object Construction</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">12.6. Instance Destructors</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 &copy; 2001</a> O'Reilly &amp; 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 + -