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

📄 ch11_08.htm

📁 By Tom Christiansen and Nathan Torkington ISBN 1-56592-243-3 First Edition, published August 1998
💻 HTM
字号:
<HTML><HEAD><TITLE>Recipe 11.7. Using Closures Instead of Objects (Perl Cookbook)</TITLE><METANAME="DC.title"CONTENT="Perl Cookbook"><METANAME="DC.creator"CONTENT="Tom Christiansen &amp; Nathan Torkington"><METANAME="DC.publisher"CONTENT="O'Reilly &amp; Associates, Inc."><METANAME="DC.date"CONTENT="1999-07-02T01:40:37Z"><METANAME="DC.type"CONTENT="Text.Monograph"><METANAME="DC.format"CONTENT="text/html"SCHEME="MIME"><METANAME="DC.source"CONTENT="1-56592-243-3"SCHEME="ISBN"><METANAME="DC.language"CONTENT="en-US"><METANAME="generator"CONTENT="Jade 1.1/O'Reilly DocBook 3.0 to HTML 4.0"><LINKREV="made"HREF="mailto:online-books@oreilly.com"TITLE="Online Books Comments"><LINKREL="up"HREF="ch11_01.htm"TITLE="11. References and Records"><LINKREL="prev"HREF="ch11_07.htm"TITLE="11.6. Creating Arrays of Scalar References"><LINKREL="next"HREF="ch11_09.htm"TITLE="11.8. Creating References to Methods"></HEAD><BODYBGCOLOR="#FFFFFF"><img alt="Book Home" border="0" src="gifs/smbanner.gif" usemap="#banner-map" /><map name="banner-map"><area shape="rect" coords="1,-2,616,66" href="index.htm" alt="Perl Cookbook"><area shape="rect" coords="629,-11,726,25" href="jobjects/fsearch.htm" alt="Search this book" /></map><div class="navbar"><p><TABLEWIDTH="684"BORDER="0"CELLSPACING="0"CELLPADDING="0"><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch11_07.htm"TITLE="11.6. Creating Arrays of Scalar References"><IMGSRC="../gifs/txtpreva.gif"ALT="Previous: 11.6. Creating Arrays of Scalar References"BORDER="0"></A></TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><B><FONTFACE="ARIEL,HELVETICA,HELV,SANSERIF"SIZE="-1"><ACLASS="chapter"REL="up"HREF="ch11_01.htm"TITLE="11. References and Records"></A></FONT></B></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch11_09.htm"TITLE="11.8. Creating References to Methods"><IMGSRC="../gifs/txtnexta.gif"ALT="Next: 11.8. Creating References to Methods"BORDER="0"></A></TD></TR></TABLE></DIV><DIVCLASS="sect1"><H2CLASS="sect1"><ACLASS="title"NAME="ch11-26813">11.7. Using Closures Instead of Objects</A></H2><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch11-pgfId-798">Problem</A></H3><PCLASS="para"><ACLASS="indexterm"NAME="ch11-idx-1000004831-0"></A><ACLASS="indexterm"NAME="ch11-idx-1000004831-1"></A><ACLASS="indexterm"NAME="ch11-idx-1000004831-2"></A><ACLASS="indexterm"NAME="ch11-idx-1000004831-3"></A>You want records with private state, behavior, and identity, but you don't want to learn object-oriented programming to accomplish this.</P></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch11-pgfId-804">Solution</A></H3><PCLASS="para">Write a function that returns (by reference) a hash of code references. These code references are all closures created in the same scope, so when they execute, they'll all share the same set of bindings to private variables.</P></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch11-pgfId-810">Discussion</A></H3><PCLASS="para">Because a closure is a binding of code and data, it can implement what might be thought of as an object.</P><PCLASS="para">Here's an example that creates and returns a hash of anonymous functions. <CODECLASS="literal">mkcounter</CODE> takes an argument of a seed counter and returns a hash reference that you can use to manipulate the counter indirectly.</P><PRECLASS="programlisting">$c1 = mkcounter(20); $c2 = mkcounter(77);printf &quot;next c1: %d\n&quot;, $c1-&gt;{NEXT}-&gt;();  # 21 printf &quot;next c2: %d\n&quot;, $c2-&gt;{NEXT}-&gt;();  # 78 printf &quot;next c1: %d\n&quot;, $c1-&gt;{NEXT}-&gt;();  # 22 printf &quot;last c1: %d\n&quot;, $c1-&gt;{PREV}-&gt;();  # 21 printf &quot;old  c2: %d\n&quot;, $c2-&gt;{RESET}-&gt;(); # 77</PRE><PCLASS="para">The code values in the hash references in <CODECLASS="literal">$c1</CODE> and <CODECLASS="literal">$c2</CODE> maintain their own separate state. Here's how to set that up:</P><PRECLASS="programlisting">sub mkcounter {    my $count  = shift;     my $start  = $count;     my $bundle = {         &quot;NEXT&quot;   =&gt; sub { return ++$count  },         &quot;PREV&quot;   =&gt; sub { return --$count  },         &quot;GET&quot;    =&gt; sub { return $count    },        &quot;SET&quot;    =&gt; sub { $count = shift   },         &quot;BUMP&quot;   =&gt; sub { $count += shift  },         &quot;RESET&quot;  =&gt; sub { $count = $start  },    };     $bundle-&gt;{&quot;LAST&quot;} = $bundle-&gt;{&quot;PREV&quot;};     return $bundle;}</PRE><PCLASS="para">Because the lexical variables used by the closures in the <CODECLASS="literal">$bundle</CODE> hash reference are returned by the function, they are not deallocated. The next time <CODECLASS="literal">mkcounter</CODE> is called, the closures get a different set of variable bindings for the same code. Because no one outside of those closures can access these two variables, this assures you of true privacy.</P><PCLASS="para">The assignment right before the return makes both the <CODECLASS="literal">&quot;PREV&quot;</CODE> and <CODECLASS="literal">&quot;LAST&quot;</CODE> values point to the same closure. Depending on your object-oriented background, you might think of these as being two different messages, both implemented using the same method.</P><PCLASS="para">The bundle we return is not an object in that it has no obvious inheritance and polymorphism. (Yet.) But it certainly does have state, behavior, and identity, as well as encapsulation.<ACLASS="indexterm"NAME="ch11-idx-1000004833-0"></A><ACLASS="indexterm"NAME="ch11-idx-1000004833-1"></A><ACLASS="indexterm"NAME="ch11-idx-1000004833-2"></A><ACLASS="indexterm"NAME="ch11-idx-1000004833-3"></A></P></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch11-pgfId-870">See Also</A></H3><PCLASS="para">The section on  <ACLASS="olink"HREF="../prog/ch04_03.htm#PERL2-CH-4-SECT-3.6">"Closures"</A> in <ACLASS="olink"HREF="../prog/ch04_01.htm">Chapter 4</A> of <ACLASS="citetitle"HREF="../prog/index.htm"TITLE="Programming Perl"><CITECLASS="citetitle">Programming Perl</CITE></A> and the discussion on closures in <ICLASS="filename">perlref </I>(1); <ACLASS="xref"HREF="ch11_05.htm"TITLE="Taking References to Functions">Recipe 11.4</A>; <ACLASS="xref"HREF="ch11_10.htm"TITLE="Constructing Records">Recipe 11.9</A>; <ACLASS="xref"HREF="ch13_01.htm"TITLE="Classes, Objects, and Ties">Chapter 13</A></P></DIV></DIV><DIVCLASS="htmlnav"><P></P><HRALIGN="LEFT"WIDTH="684"TITLE="footer"><TABLEWIDTH="684"BORDER="0"CELLSPACING="0"CELLPADDING="0"><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch11_07.htm"TITLE="11.6. Creating Arrays of Scalar References"><IMGSRC="../gifs/txtpreva.gif"ALT="Previous: 11.6. Creating Arrays of Scalar References"BORDER="0"></A></TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><ACLASS="book"HREF="index.htm"TITLE="Perl Cookbook"><IMGSRC="../gifs/txthome.gif"ALT="Perl Cookbook"BORDER="0"></A></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch11_09.htm"TITLE="11.8. Creating References to Methods"><IMGSRC="../gifs/txtnexta.gif"ALT="Next: 11.8. Creating References to Methods"BORDER="0"></A></TD></TR><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228">11.6. Creating Arrays of Scalar References</TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><ACLASS="index"HREF="index/index.htm"TITLE="Book Index"><IMGSRC="../gifs/index.gif"ALT="Book Index"BORDER="0"></A></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228">11.8. Creating References to Methods</TD></TR></TABLE><HRALIGN="LEFT"WIDTH="684"TITLE="footer"><FONTSIZE="-1"></DIV<!-- LIBRARY NAV BAR --> <img src="../gifs/smnavbar.gif" usemap="#library-map" border="0" alt="Library Navigation Links"><p> <a href="copyrght.htm">Copyright &copy; 2002</a> O'Reilly &amp; Associates. All rights reserved.</font> </p> <map name="library-map"> <area shape="rect" coords="1,0,85,94" href="../index.htm"><area shape="rect" coords="86,1,178,103" href="../lwp/index.htm"><area shape="rect" coords="180,0,265,103" href="../lperl/index.htm"><area shape="rect" coords="267,0,353,105" href="../perlnut/index.htm"><area shape="rect" coords="354,1,446,115" href="../prog/index.htm"><area shape="rect" coords="448,0,526,132" href="../tk/index.htm"><area shape="rect" coords="528,1,615,119" href="../cookbook/index.htm"><area shape="rect" coords="617,0,690,135" href="../pxml/index.htm"></map> </BODY></HTML>

⌨️ 快捷键说明

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