next.html
来自「perl教程」· HTML 代码 · 共 431 行 · 第 1/3 页
HTML
431 行
<?xml version="1.0" ?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<!-- saved from url=(0017)http://localhost/ -->
<script language="JavaScript" src="../displayToc.js"></script>
<script language="JavaScript" src="../tocParas.js"></script>
<script language="JavaScript" src="../tocTab.js"></script>
<link rel="stylesheet" type="text/css" href="../scineplex.css">
<title>NEXT.pm - Provide a pseudo-class NEXT that allows method redispatch</title>
<link rel="stylesheet" href="../Active.css" type="text/css" />
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<link rev="made" href="mailto:" />
</head>
<body>
<script>writelinks('__top__',1);</script>
<h1><a>NEXT.pm - Provide a pseudo-class NEXT that allows method redispatch</a></h1>
<p><a name="__index__"></a></p>
<!-- INDEX BEGIN -->
<ul>
<li><a href="#name">NAME</a></li>
<li><a href="#synopsis">SYNOPSIS</a></li>
<li><a href="#description">DESCRIPTION</a></li>
<ul>
<li><a href="#enforcing_redispatch">Enforcing redispatch</a></li>
<li><a href="#avoiding_repetitions">Avoiding repetitions</a></li>
<li><a href="#invoking_all_versions_of_a_method_with_a_single_call">Invoking all versions of a method with a single call</a></li>
<li><a href="#using_every_methods">Using <code>EVERY</code> methods</a></li>
</ul>
<li><a href="#author">AUTHOR</a></li>
<li><a href="#bugs_and_irritations">BUGS AND IRRITATIONS</a></li>
<li><a href="#copyright">COPYRIGHT</a></li>
</ul>
<!-- INDEX END -->
<hr />
<p>
</p>
<h1><a name="name">NAME</a></h1>
<p>NEXT.pm - Provide a pseudo-class NEXT (et al) that allows method redispatch</p>
<p>
</p>
<hr />
<h1><a name="synopsis">SYNOPSIS</a></h1>
<pre>
<span class="keyword">use</span> <span class="variable">NEXT</span><span class="operator">;</span>
</pre>
<pre>
<span class="keyword">package</span> <span class="variable">A</span><span class="operator">;</span>
<span class="keyword">sub</span><span class="variable"> A::method </span><span class="operator">{</span> <span class="keyword">print</span> <span class="string">"$_[0]: A method\n"</span><span class="operator">;</span> <span class="variable">$_</span><span class="operator">[</span><span class="number">0</span><span class="operator">]</span><span class="operator">-></span><span class="variable">NEXT::method</span><span class="operator">()</span> <span class="operator">}</span>
<span class="keyword">sub</span><span class="variable"> A::DESTROY </span><span class="operator">{</span> <span class="keyword">print</span> <span class="string">"$_[0]: A dtor\n"</span><span class="operator">;</span> <span class="variable">$_</span><span class="operator">[</span><span class="number">0</span><span class="operator">]</span><span class="operator">-></span><span class="variable">NEXT::DESTROY</span><span class="operator">()</span> <span class="operator">}</span>
</pre>
<pre>
<span class="keyword">package</span> <span class="variable">B</span><span class="operator">;</span>
<span class="keyword">use</span> <span class="variable">base</span> <span class="string">qw( A )</span><span class="operator">;</span>
<span class="keyword">sub</span><span class="variable"> B::AUTOLOAD </span><span class="operator">{</span> <span class="keyword">print</span> <span class="string">"$_[0]: B AUTOLOAD\n"</span><span class="operator">;</span> <span class="variable">$_</span><span class="operator">[</span><span class="number">0</span><span class="operator">]</span><span class="operator">-></span><span class="variable">NEXT::AUTOLOAD</span><span class="operator">()</span> <span class="operator">}</span>
<span class="keyword">sub</span><span class="variable"> B::DESTROY </span><span class="operator">{</span> <span class="keyword">print</span> <span class="string">"$_[0]: B dtor\n"</span><span class="operator">;</span> <span class="variable">$_</span><span class="operator">[</span><span class="number">0</span><span class="operator">]</span><span class="operator">-></span><span class="variable">NEXT::DESTROY</span><span class="operator">()</span> <span class="operator">}</span>
</pre>
<pre>
<span class="keyword">package</span> <span class="variable">C</span><span class="operator">;</span>
<span class="keyword">sub</span><span class="variable"> C::method </span><span class="operator">{</span> <span class="keyword">print</span> <span class="string">"$_[0]: C method\n"</span><span class="operator">;</span> <span class="variable">$_</span><span class="operator">[</span><span class="number">0</span><span class="operator">]</span><span class="operator">-></span><span class="variable">NEXT::method</span><span class="operator">()</span> <span class="operator">}</span>
<span class="keyword">sub</span><span class="variable"> C::AUTOLOAD </span><span class="operator">{</span> <span class="keyword">print</span> <span class="string">"$_[0]: C AUTOLOAD\n"</span><span class="operator">;</span> <span class="variable">$_</span><span class="operator">[</span><span class="number">0</span><span class="operator">]</span><span class="operator">-></span><span class="variable">NEXT::AUTOLOAD</span><span class="operator">()</span> <span class="operator">}</span>
<span class="keyword">sub</span><span class="variable"> C::DESTROY </span><span class="operator">{</span> <span class="keyword">print</span> <span class="string">"$_[0]: C dtor\n"</span><span class="operator">;</span> <span class="variable">$_</span><span class="operator">[</span><span class="number">0</span><span class="operator">]</span><span class="operator">-></span><span class="variable">NEXT::DESTROY</span><span class="operator">()</span> <span class="operator">}</span>
</pre>
<pre>
<span class="keyword">package</span> <span class="variable">D</span><span class="operator">;</span>
<span class="keyword">use</span> <span class="variable">base</span> <span class="string">qw( B C )</span><span class="operator">;</span>
<span class="keyword">sub</span><span class="variable"> D::method </span><span class="operator">{</span> <span class="keyword">print</span> <span class="string">"$_[0]: D method\n"</span><span class="operator">;</span> <span class="variable">$_</span><span class="operator">[</span><span class="number">0</span><span class="operator">]</span><span class="operator">-></span><span class="variable">NEXT::method</span><span class="operator">()</span> <span class="operator">}</span>
<span class="keyword">sub</span><span class="variable"> D::AUTOLOAD </span><span class="operator">{</span> <span class="keyword">print</span> <span class="string">"$_[0]: D AUTOLOAD\n"</span><span class="operator">;</span> <span class="variable">$_</span><span class="operator">[</span><span class="number">0</span><span class="operator">]</span><span class="operator">-></span><span class="variable">NEXT::AUTOLOAD</span><span class="operator">()</span> <span class="operator">}</span>
<span class="keyword">sub</span><span class="variable"> D::DESTROY </span><span class="operator">{</span> <span class="keyword">print</span> <span class="string">"$_[0]: D dtor\n"</span><span class="operator">;</span> <span class="variable">$_</span><span class="operator">[</span><span class="number">0</span><span class="operator">]</span><span class="operator">-></span><span class="variable">NEXT::DESTROY</span><span class="operator">()</span> <span class="operator">}</span>
</pre>
<pre>
<span class="keyword">package</span> <span class="variable">main</span><span class="operator">;</span>
</pre>
<pre>
<span class="keyword">my</span> <span class="variable">$obj</span> <span class="operator">=</span> <span class="keyword">bless</span> <span class="operator">{}</span><span class="operator">,</span> <span class="string">"D"</span><span class="operator">;</span>
</pre>
<pre>
<span class="variable">$obj</span><span class="operator">-></span><span class="variable">method</span><span class="operator">();</span> <span class="comment"># Calls D::method, A::method, C::method</span>
<span class="variable">$obj</span><span class="operator">-></span><span class="variable">missing_method</span><span class="operator">();</span> <span class="comment"># Calls D::AUTOLOAD, B::AUTOLOAD, C::AUTOLOAD</span>
</pre>
<pre>
<span class="comment"># Clean-up calls D::DESTROY, B::DESTROY, A::DESTROY, C::DESTROY</span>
</pre>
<p>
</p>
<hr />
<h1><a name="description">DESCRIPTION</a></h1>
<p>NEXT.pm adds a pseudoclass named <code>NEXT</code> to any program
that uses it. If a method <a href="../lib/Pod/perlguts.html#item_m"><code>m</code></a> calls <a href="../lib/Pod/perlguts.html#item_m"><code>$self->NEXT::m()</code></a>, the call to
<a href="../lib/Pod/perlguts.html#item_m"><code>m</code></a> is redispatched as if the calling method had not originally been found.</p>
<p>In other words, a call to <a href="../lib/Pod/perlguts.html#item_m"><code>$self->NEXT::m()</code></a> resumes the depth-first,
left-to-right search of <code>$self</code>'s class hierarchy that resulted in the
original call to <a href="../lib/Pod/perlguts.html#item_m"><code>m</code></a>.</p>
<p>Note that this is not the same thing as <a href="../lib/Pod/perlguts.html#item_m"><code>$self->SUPER::m()</code></a>, which
begins a new dispatch that is restricted to searching the ancestors
of the current class. <a href="../lib/Pod/perlguts.html#item_m"><code>$self->NEXT::m()</code></a> can backtrack
past the current class -- to look for a suitable method in other
ancestors of <code>$self</code> -- whereas <a href="../lib/Pod/perlguts.html#item_m"><code>$self->SUPER::m()</code></a> cannot.</p>
<p>A typical use would be in the destructors of a class hierarchy,
as illustrated in the synopsis above. Each class in the hierarchy
has a DESTROY method that performs some class-specific action
and then redispatches the call up the hierarchy. As a result,
when an object of class D is destroyed, the destructors of <em>all</em>
its parent classes are called (in depth-first, left-to-right order).</p>
<p>Another typical use of redispatch would be in <code>AUTOLOAD</code>'ed methods.
If such a method determined that it was not able to handle a
particular call, it might choose to redispatch that call, in the
hope that some other <code>AUTOLOAD</code> (above it, or to its left) might
do better.</p>
<p>By default, if a redispatch attempt fails to find another method
elsewhere in the objects class hierarchy, it quietly gives up and does
nothing (but see <a href="#enforcing_redispatch">Enforcing redispatch</a>). This gracious acquiesence
is also unlike the (generally annoying) behaviour of <code>SUPER</code>, which
throws an exception if it cannot redispatch.</p>
<p>Note that it is a fatal error for any method (including <code>AUTOLOAD</code>)
to attempt to redispatch any method that does not have the
same name. For example:</p>
<pre>
<span class="keyword">sub</span><span class="variable"> D::oops </span><span class="operator">{</span> <span class="keyword">print</span> <span class="string">"oops!\n"</span><span class="operator">;</span> <span class="variable">$_</span><span class="operator">[</span><span class="number">0</span><span class="operator">]</span><span class="operator">-></span><span class="variable">NEXT::other_method</span><span class="operator">()</span> <span class="operator">}</span>
</pre>
<p>
</p>
<h2><a name="enforcing_redispatch">Enforcing redispatch</a></h2>
<p>It is possible to make <code>NEXT</code> redispatch more demandingly (i.e. like
<code>SUPER</code> does), so that the redispatch throws an exception if it cannot
find a "next" method to call.</p>
<p>To do this, simple invoke the redispatch as:</p>
<pre>
<span class="variable">$self</span><span class="operator">-></span><span class="variable">NEXT::ACTUAL::method</span><span class="operator">();</span>
</pre>
<p>rather than:</p>
<pre>
<span class="variable">$self</span><span class="operator">-></span><span class="variable">NEXT::method</span><span class="operator">();</span>
</pre>
<p>The <code>ACTUAL</code> tells <code>NEXT</code> that there must actually be a next method to call,
or it should throw an exception.</p>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?