📄 ch08_02.htm
字号:
<a name="FOOTNOTE-2"></a><p>[2]But even though there's only one anonymoussubroutine, there may be several copies of the lexical variables inuse by the subroutine, depending on when the subroutine reference wasgenerated. These are discussed later in the section <a href="ch08_03.htm#ch08-sect-closure">Section 8.3.7, "Closures"</a>.</p></blockquote><a name="INDEX-1989"></a><h3 class="sect2">8.2.3. Object Constructors</h3><a name="INDEX-1990"></a><a name="INDEX-1991"></a><a name="INDEX-1992"></a><a name="INDEX-1993"></a><a name="INDEX-1994"></a><p>Subroutines can also return references. That may sound trite, butsometimes you are <em class="emphasis">supposed</em> to use a subroutine to create areference rather than creating the reference yourself. In particular,special subroutines called <em class="emphasis">constructors</em> create and return references toobjects. An object is simply a special kind of reference that happensto know which class it's associated with, and constructors know how tocreate that association. They do so by taking an ordinary referentand turning it into an object with the <tt class="literal">bless</tt> operator, so we canspeak of an object as a blessed reference. There's nothing religiousgoing on here; since a class acts as a user-defined type, blessinga referent simply makes it a user-defined type in addition to a built-inone. Constructors are often named <tt class="literal">new</tt>--especially by C++programmers--but they can be named anything in Perl.</p><p>Constructors can be called in any of these ways:<blockquote><pre class="programlisting">$objref = Doggie::->new(Tail => 'short', Ears => 'long'); #1$objref = new Doggie:: Tail => 'short', Ears => 'long'; #2$objref = Doggie->new(Tail => 'short', Ears => 'long'); #3$objref = new Doggie Tail => 'short', Ears => 'long'; #4</pre></blockquote>The first and second invocations are the same. They both call afunction named <tt class="literal">new</tt> that is supplied by the <tt class="literal">Doggie</tt> module. Thethird and fourth invocations are the same as the first two, but areslightly more ambiguous: the parser will get confused if you defineyour own subroutine named <tt class="literal">Doggie</tt>. (Which is why people typicallystick with lowercase names for subroutines and uppercase for modules.)The fourth invocation can also get confused if you've defined your own<tt class="literal">new</tt> subroutine and don't happen to have done either a <tt class="literal">require</tt> ora <tt class="literal">use</tt> of the <tt class="literal">Doggie</tt> module, either of which has the effect ofdeclaring the module. Always declare your modules if you want to use #4.(And watch out for stray <tt class="literal">Doggie</tt> subroutines.)</p><p>See <a href="ch12_01.htm">Chapter 12, "Objects"</a> for a discussion of Perl objects.</p><a name="ch08-sect-hr"></a><h3 class="sect2">8.2.4. Handle References</h3><a name="INDEX-1995"></a><a name="INDEX-1996"></a><a name="INDEX-1997"></a><a name="INDEX-1998"></a><p>References to filehandles or directory handles can be created byreferencing the typeglob of the same name:<blockquote><pre class="programlisting">splutter(\*STDOUT);sub splutter { my $fh = shift; print $fh "her um well a hmmm\n";}$rec = get_rec(\*STDIN);sub get_rec { my $fh = shift; return scalar <$fh>;}</pre></blockquote>If you're passing around filehandles, you can also use the baretypeglob to do so: in the example above, you could have used<tt class="literal">*STDOUT</tt> or <tt class="literal">*STDIN</tt> instead of <tt class="literal">\*STDOUT</tt> and <tt class="literal">\*STDIN</tt>.</p><p><a name="INDEX-1999"></a>Although you can usually use typeglob and references to typeglobsinterchangeably, there are a few places where you can't. Simple typeglobscan't be <tt class="literal">bless</tt>ed into objectdom, and typeglob references can'tbe passed back out of the scope of a localized typeglob.</p><p>When generating new filehandles, older code would often do somethinglike this to open a list of files:<blockquote><pre class="programlisting">for $file (@names) { local *FH; open(*FH, $file) || next; $handle{$file} = *FH;}</pre></blockquote></p><p><a name="INDEX-2000"></a><a name="INDEX-2001"></a>That still works, but now it's just as easy to let an undefinedvariable autovivify an anonymous typeglob:<blockquote><pre class="programlisting">for $file (@names) { my $fh; open($fh, $file) || next; $handle{$file} = $fh;}</pre></blockquote>With indirect filehandles, it doesn't matter whether you use usetypeglobs, references to typeglobs, or one of the more exotic I/Oobjects. You just use a scalar that--one way or another--getsinterpreted as a filehandle. For most purposes, you can use either atypeglob or a typeglob reference almost indiscriminately. As weadmitted earlier, there is some implicit dereferencing magic goingon here.</p><a name="ch08-sect-str"></a><h3 class="sect2">8.2.5. Symbol Table References</h3><p><a name="INDEX-2002"></a><a name="INDEX-2003"></a>In unusual circumstances, you might not know what type of referenceyou need when your program is written. A reference can be created byusing a special syntax, affectionately known as the <tt class="literal">*foo{</tt><em class="replaceable">THING</em><tt class="literal">}</tt>syntax. <tt class="literal">*foo{</tt><em class="replaceable">THING</em><tt class="literal">}</tt> returns a reference to the <em class="replaceable">THING</em> slot in<tt class="literal">*foo</tt>, which is the symbol table entry holding the values of <tt class="literal">$foo</tt>,<tt class="literal">@foo</tt>, <tt class="literal">%foo</tt>, and friends.<blockquote><pre class="programlisting">$scalarref = *foo{SCALAR}; # Same as \$foo$arrayref = *ARGV{ARRAY}; # Same as \@ARGV$hashref = *ENV{HASH}; # Same as \%ENV$coderef = *handler{CODE}; # Same as \&handler$globref = *foo{GLOB}; # Same as \*foo$ioref = *STDIN{IO}; # Er...</pre></blockquote><a name="INDEX-2004"></a>All of these are self-explanatory except for <tt class="literal">*STDIN{IO}</tt>. It yieldsthe actual internal <tt class="literal">IO::Handle</tt> object that the typeglob contains, thatis, the part of the typeglob that the various I/O functions areactually interested in. For compatibility with previous versions ofPerl, <tt class="literal">*foo{FILEHANDLE}</tt> is a synonym for the hipper <tt class="literal">*foo{IO}</tt>notation.</p><p>In theory, you can use a <tt class="literal">*</tt><em class="replaceable">HANDLE</em><tt class="literal">{IO}</tt> anywhere you'd use a <tt class="literal">*</tt><em class="replaceable">HANDLE</em> or a <tt class="literal">\*</tt><em class="replaceable">HANDLE</em>, such as for passing handlesinto or out of subroutines, or storing them in larger data structures.(In practice, there are still some wrinkles to be ironed out.) Theadvantage of them is that they access only the real I/O object youwant, not the whole typeglob, so you run no risk of clobbering morethan you want to through a typeglob assignment (although if you alwaysassign to a scalar variable instead of to a typeglob, you'll be okay).One disadvantage is that there's no way to autovivify one as ofyet.<a href="#FOOTNOTE-3">[3]</a><blockquote><pre class="programlisting">splutter(*STDOUT);splutter(*STDOUT{IO});sub splutter { my $fh = shift; print $fh "her um well a hmmm\n";}</pre></blockquote>Both invocations of <tt class="literal">splutter()</tt> print "<tt class="literal">her um well a hmmm</tt>".</p><blockquote class="footnote"><a name="FOOTNOTE-3"></a><p>[3] Currently, <tt class="literal">open my $fh</tt> autovivifies a typeglob insteadof an <tt class="literal">IO::Handle</tt> object, but someday we may fix that, so youshouldn't rely on the typeglobbedess of what <tt class="literal">open</tt> currentlyautovivifies.</p></blockquote><p>The <tt class="literal">*foo{</tt><em class="replaceable">THING</em><tt class="literal">}</tt> thing returns <tt class="literal">undef</tt> if that particular<em class="replaceable">THING</em> hasn't been seen by the compiler yet, except when <em class="replaceable">THING</em> is<tt class="literal">SCALAR</tt>. It so happens that <tt class="literal">*foo{SCALAR}</tt> returns a reference toan anonymous scalar even if <tt class="literal">$foo</tt> hasn't been seen yet. (Perl alwaysadds a scalar to any typeglob as an optimization to save a bit of codeelsewhere. But don't depend on it to stay that way in future releases.)</p><h3 class="sect2">8.2.6. Implicit Creation of References</h3><p>A final method for creating references is not really a method at all.References of an appropriate type simply spring into existence if youdereference them in an lvalue context that assumes they exist. This isextremely useful, and is also What You Expect. This topic is coveredlater in this chapter, where we'll discuss how to dereference all of thereferences we've created so far.</p><a name="INDEX-2005"></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="ch08_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="ch08_03.htm"><img src="../gifs/txtnexta.gif" alt="Next" border="0"></a></td></tr><tr><td align="left" valign="top" width="172">8.1. What Is a Reference?</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">8.3. Using Hard References</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 + -