perltie.html

来自「perl教程」· HTML 代码 · 共 838 行 · 第 1/5 页

HTML
838
字号
<?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>perltie - how to hide an object class in a simple variable</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__',2);</script>
<h1><a>perltie - how to hide an object class in a simple variable</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="#tying_scalars">Tying Scalars</a></li>
		<li><a href="#tying_arrays">Tying Arrays</a></li>
		<li><a href="#tying_hashes">Tying Hashes</a></li>
		<li><a href="#tying_filehandles">Tying FileHandles</a></li>
		<li><a href="#untie_this">UNTIE this</a></li>
		<li><a href="#the_untie_gotcha">The <a href="../../lib/Pod/perlfunc.html#item_untie"><code>untie</code></a> Gotcha</a></li>
	</ul>

	<li><a href="#see_also">SEE ALSO</a></li>
	<li><a href="#bugs">BUGS</a></li>
	<li><a href="#author">AUTHOR</a></li>
</ul>
<!-- INDEX END -->

<hr />
<p>
</p>
<h1><a name="name">NAME</a></h1>
<p>perltie - how to hide an object class in a simple variable</p>
<p>
</p>
<hr />
<h1><a name="synopsis">SYNOPSIS</a></h1>
<pre>
 tie VARIABLE, CLASSNAME, LIST</pre>
<pre>
 $object = tied VARIABLE</pre>
<pre>
 untie VARIABLE</pre>
<p>
</p>
<hr />
<h1><a name="description">DESCRIPTION</a></h1>
<p>Prior to release 5.0 of Perl, a programmer could use <a href="../../lib/Pod/perlfunc.html#item_dbmopen"><code>dbmopen()</code></a>
to connect an on-disk database in the standard Unix <code>dbm(3x)</code>
format magically to a %HASH in their program.  However, their Perl was either
built with one particular dbm library or another, but not both, and
you couldn't extend this mechanism to other packages or types of variables.</p>
<p>Now you can.</p>
<p>The <a href="../../lib/Pod/perlfunc.html#item_tie"><code>tie()</code></a> function binds a variable to a class (package) that will provide
the implementation for access methods for that variable.  Once this magic
has been performed, accessing a tied variable automatically triggers
method calls in the proper class.  The complexity of the class is
hidden behind magic methods calls.  The method names are in ALL CAPS,
which is a convention that Perl uses to indicate that they're called
implicitly rather than explicitly--just like the <code>BEGIN()</code> and <code>END()</code>
functions.</p>
<p>In the <a href="../../lib/Pod/perlfunc.html#item_tie"><code>tie()</code></a> call, <code>VARIABLE</code> is the name of the variable to be
enchanted.  <code>CLASSNAME</code> is the name of a class implementing objects of
the correct type.  Any additional arguments in the <a href="#item_list"><code>LIST</code></a> are passed to
the appropriate constructor method for that class--meaning TIESCALAR(),
TIEARRAY(), TIEHASH(), or TIEHANDLE().  (Typically these are arguments
such as might be passed to the <code>dbminit()</code> function of C.) The object
returned by the &quot;new&quot; method is also returned by the <a href="../../lib/Pod/perlfunc.html#item_tie"><code>tie()</code></a> function,
which would be useful if you wanted to access other methods in
<code>CLASSNAME</code>. (You don't actually have to return a reference to a right
&quot;type&quot; (e.g., HASH or <code>CLASSNAME</code>) so long as it's a properly blessed
object.)  You can also retrieve a reference to the underlying object
using the <a href="../../lib/Pod/perlfunc.html#item_tied"><code>tied()</code></a> function.</p>
<p>Unlike dbmopen(), the <a href="../../lib/Pod/perlfunc.html#item_tie"><code>tie()</code></a> function will not <a href="../../lib/Pod/perlfunc.html#item_use"><code>use</code></a> or <a href="../../lib/Pod/perlfunc.html#item_require"><code>require</code></a> a module
for you--you need to do that explicitly yourself.</p>
<p>
</p>
<h2><a name="tying_scalars">Tying Scalars</a></h2>
<p>A class implementing a tied scalar should define the following methods:
TIESCALAR, FETCH, STORE, and possibly UNTIE and/or DESTROY.</p>
<p>Let's look at each in turn, using as an example a tie class for
scalars that allows the user to do something like:</p>
<pre>
    <span class="keyword">tie</span> <span class="variable">$his_speed</span><span class="operator">,</span> <span class="string">'Nice'</span><span class="operator">,</span> <span class="keyword">getppid</span><span class="operator">();</span>
    <span class="keyword">tie</span> <span class="variable">$my_speed</span><span class="operator">,</span>  <span class="string">'Nice'</span><span class="operator">,</span> <span class="variable">$$</span><span class="operator">;</span>
</pre>
<p>And now whenever either of those variables is accessed, its current
system priority is retrieved and returned.  If those variables are set,
then the process's priority is changed!</p>
<p>We'll use Jarkko Hietaniemi &lt;<em><a href="mailto:jhi@iki.fi">jhi@iki.fi</a></em>&gt;'s BSD::Resource class (not
included) to access the PRIO_PROCESS, PRIO_MIN, and PRIO_MAX constants
from your system, as well as the <a href="../../lib/Pod/perlfunc.html#item_getpriority"><code>getpriority()</code></a> and <a href="../../lib/Pod/perlfunc.html#item_setpriority"><code>setpriority()</code></a> system
calls.  Here's the preamble of the class.</p>
<pre>
    <span class="keyword">package</span> <span class="variable">Nice</span><span class="operator">;</span>
    <span class="keyword">use</span> <span class="variable">Carp</span><span class="operator">;</span>
    <span class="keyword">use</span> <span class="variable">BSD::Resource</span><span class="operator">;</span>
    <span class="keyword">use</span> <span class="variable">strict</span><span class="operator">;</span>
    <span class="variable">$Nice::DEBUG</span> <span class="operator">=</span> <span class="number">0</span> <span class="keyword">unless</span> <span class="keyword">defined</span> <span class="variable">$Nice::DEBUG</span><span class="operator">;</span>
</pre>
<dl>
<dt><strong><a name="item_tiescalar_classname_2c_list">TIESCALAR classname, LIST</a></strong>

<dd>
<p>This is the constructor for the class.  That means it is
expected to return a blessed reference to a new scalar
(probably anonymous) that it's creating.  For example:</p>
</dd>
<dd>
<pre>
    <span class="keyword">sub</span><span class="variable"> TIESCALAR </span><span class="operator">{</span>
        <span class="keyword">my</span> <span class="variable">$class</span> <span class="operator">=</span> <span class="keyword">shift</span><span class="operator">;</span>
        <span class="keyword">my</span> <span class="variable">$pid</span> <span class="operator">=</span> <span class="keyword">shift</span> <span class="operator">||</span> <span class="variable">$$</span><span class="operator">;</span> <span class="comment"># 0 means me</span>
</pre>
</dd>
<dd>
<pre>
        <span class="keyword">if</span> <span class="operator">(</span><span class="variable">$pid</span> <span class="operator">!~</span> <span class="regex">/^\d+$/</span><span class="operator">)</span> <span class="operator">{</span>
            <span class="variable">carp</span> <span class="string">"Nice::Tie::Scalar got non-numeric pid $pid"</span> <span class="keyword">if</span> <span class="variable">$^W</span><span class="operator">;</span>
            <span class="keyword">return</span> <span class="keyword">undef</span><span class="operator">;</span>
        <span class="operator">}</span>
</pre>
</dd>
<dd>
<pre>
        <span class="keyword">unless</span> <span class="operator">(</span><span class="keyword">kill</span> <span class="number">0</span><span class="operator">,</span> <span class="variable">$pid</span><span class="operator">)</span> <span class="operator">{</span> <span class="comment"># EPERM or ERSCH, no doubt</span>
            <span class="variable">carp</span> <span class="string">"Nice::Tie::Scalar got bad pid $pid: $!"</span> <span class="keyword">if</span> <span class="variable">$^W</span><span class="operator">;</span>
            <span class="keyword">return</span> <span class="keyword">undef</span><span class="operator">;</span>
        <span class="operator">}</span>
</pre>
</dd>
<dd>
<pre>
        <span class="keyword">return</span> <span class="keyword">bless</span> <span class="operator">\</span><span class="variable">$pid</span><span class="operator">,</span> <span class="variable">$class</span><span class="operator">;</span>
            <span class="operator">}</span>
</pre>
</dd>
<dd>
<p>This tie class has chosen to return an error rather than raising an
exception if its constructor should fail.  While this is how <a href="../../lib/Pod/perlfunc.html#item_dbmopen"><code>dbmopen()</code></a> works,
other classes may well not wish to be so forgiving.  It checks the global
variable <a href="../../lib/Pod/perlvar.html#item___w"><code>$^W</code></a> to see whether to emit a bit of noise anyway.</p>
</dd>
</li>
<dt><strong><a name="item_fetch_this">FETCH this</a></strong>

<dd>
<p>This method will be triggered every time the tied variable is accessed
(read).  It takes no arguments beyond its self reference, which is the
object representing the scalar we're dealing with.  Because in this case
we're using just a SCALAR ref for the tied scalar object, a simple $$self
allows the method to get at the real value stored there.  In our example

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?