📄 ch13_03.htm
字号:
<html><head><title>Overloadable Operators (Programming Perl)</title><!-- STYLESHEET --><link rel="stylesheet" type="text/css" href="../style/style1.css"><!-- METADATA --><!--Dublin Core Metadata--><meta name="DC.Creator" content=""><meta name="DC.Date" content=""><meta name="DC.Format" content="text/xml" scheme="MIME"><meta name="DC.Generator" content="XSLT stylesheet, xt by James Clark"><meta name="DC.Identifier" content=""><meta name="DC.Language" content="en-US"><meta name="DC.Publisher" content="O'Reilly & Associates, Inc."><meta name="DC.Source" content="" scheme="ISBN"><meta name="DC.Subject.Keyword" content=""><meta name="DC.Title" content="Overloadable Operators"><meta name="DC.Type" content="Text.Monograph"></head><body><!-- START OF BODY --><!-- TOP BANNER --><img src="gifs/smbanner.gif" usemap="#banner-map" border="0" alt="Book Home"><map name="banner-map"><AREA SHAPE="RECT" COORDS="0,0,466,71" HREF="index.htm" ALT="Programming Perl"><AREA SHAPE="RECT" COORDS="467,0,514,18" HREF="jobjects/fsearch.htm" ALT="Search this book"></map><!-- TOP NAV BAR --><div class="navbar"><table width="515" border="0"><tr><td align="left" valign="top" width="172"><a href="ch13_02.htm"><img src="../gifs/txtpreva.gif" alt="Previous" border="0"></a></td><td align="center" valign="top" width="171"><a href="ch13_01.htm">Chapter 13: Overloading</a></td><td align="right" valign="top" width="172"><a href="ch13_04.htm"><img src="../gifs/txtnexta.gif" alt="Next" border="0"></a></td></tr></table></div><hr width="515" align="left"><!-- SECTION BODY --><h2 class="sect1">13.3. Overloadable Operators</h2><p><a name="INDEX-2616"></a><a name="INDEX-2617"></a>You can only overload certain operators, which are shown in <a href="ch13_03.htm#perl3-tab-overloadops">Table 13-1</a>. The operators are also listed inthe <tt class="literal">%overload::ops</tt> hash made available when you<tt class="literal">use overload</tt>, though the categorization is a littledifferent there.</p><a name="perl3-tab-overloadops"></a><h4 class="objtitle">Table 13.1. Overloadable Operators</h4><table border="1"><tr><th>Category</th><th>Operators</th></tr><tr><td>Conversion</td><td><tt class="literal">"" 0+ bool</tt></td></tr><tr><td>Arithmetic</td><td><tt class="literal">+ - * / % ** x . neg</tt></td></tr><tr><td>Logical</td><td><tt class="literal">!</tt></td></tr><tr><td>Bitwise</td><td><tt class="literal">& | ~ ^ ! << >></tt></td></tr><tr><td>Assignment</td><td><tt class="literal">+= -= *= /= %= **= x= .= <<= >>= ++ --</tt></td></tr><tr><td>Comparison</td><td><tt class="literal">== < <= > >= != <=> lt le gt ge eq ne cmp</tt></td></tr><tr><td>Mathematical</td><td><tt class="literal">atan2 cos sin exp abs log sqrt</tt></td></tr><tr><td>Iterative</td><td><tt class="literal"><></tt></td></tr><tr><td>Dereference</td><td><tt class="literal">${} @{} %{} &{} *{}</tt></td></tr><tr><td>Pseudo</td><td><tt class="literal">nomethod fallback =></tt></td></tr></table><p>Note that <tt class="literal">neg</tt>, <tt class="literal">bool</tt>,<tt class="literal">nomethod</tt>, and <tt class="literal">fallback</tt> are notactual Perl operators. The five dereferencers, <tt class="literal">""</tt>,and <tt class="literal">0+</tt> probably don't <em class="emphasis">seem</em>like operators either. Nevertheless, they are all valid keys for theparameter list you provide to <tt class="literal">use overload</tt>. Thisis not really a problem. We'll let you in on a little secret: it's abit of a fib to say that the <tt class="literal">overload</tt> pragmaoverloads operators. It overloads the underlying operations, whetherinvoked explicitly via their "official" operators, or implicitly viasome related operator. (The pseudo-operators we mentioned can only beinvoked implicitly.) In other words, overloading happens not at thesyntactic level, but at the semantic level. The point is not to lookgood. The point is to do the right thing. Feel free to generalize.<a name="INDEX-2618"></a></p><p>Note also that <tt class="literal">=</tt> does <em class="emphasis">not</em>overload Perl's assignment operator, as you might expect. That wouldnot do the right thing. More on that later.</p><p><a name="INDEX-2619"></a><a name="INDEX-2620"></a><a name="INDEX-2621"></a>We'll start by discussing the conversion operators, not becausethey're the most obvious (they aren't), but because they're the mostuseful. Many classes overload nothing but stringification, specifiedby the <tt class="literal">""</tt> key. (Yes, that really is twodouble-quotes in a row.)</p><dl><dt><b><em class="emphasis">Conversion operators:</em><tt class="literal">""</tt><em class="emphasis">,</em><tt class="literal">0+</tt><em class="emphasis">,</em><tt class="literal">bool</tt></b></dt><dd><p><a name="INDEX-"></a>These three keys let you provide behaviors for Perl's automaticconversions to strings, numbers, and Boolean values, respectively.</p><a name="INDEX-"></a><p>We say that <em class="emphasis">stringification</em> occurs when anynonstring variable is used as a string. It's what happens when youconvert a variable into a string via printing, interpolation,concatenation, or even by using it as a hash key. Stringification isalso why you see something like <tt class="literal">SCALAR(0xba5fe0)</tt>when you try to <tt class="literal">print</tt> an object.</p><p><a name="INDEX-"></a><a name="INDEX-"></a>We say that <em class="emphasis">numification</em> occurs when a nonnumericvariable is converted into a number in any numeric context,such as any mathematical expression, array index, or even as anoperand of the <tt class="literal">..</tt> range operator.</p><p><a name="INDEX-"></a><a name="INDEX-"></a>Finally, while nobody here quite has the nerve to call it<em class="emphasis">boolification</em>, you can define how an objectshould be interpreted in a Boolean context (such as<tt class="literal">if</tt>, <tt class="literal">unless</tt>,<tt class="literal">while</tt>, <tt class="literal">for</tt>,<tt class="literal">and</tt>, <tt class="literal">or</tt>, <tt class="literal">&&</tt>,<tt class="literal">||</tt>, <tt class="literal">?:</tt>, or the block of a<tt class="literal">grep</tt> expression) by creating a<tt class="literal">bool</tt> handler.</p><p>Any of the three conversion operators can be<em class="emphasis">autogenerated</em> if you have any one of them (we'llexplain autogeneration later). Your handlers can return any value youlike. Note that if the operation that triggered the conversion isalso overloaded, <em class="emphasis">that</em> overloading will occurimmediately afterward.</p><p><a name="INDEX-"></a>Here's a demonstration of <tt class="literal">""</tt> that invokes anobject's <tt class="literal">as_string</tt> handler upon stringification.Don't forget to quote the quotes:<blockquote><pre class="programlisting">package Person;use overload q("") => \&as_string;sub new { my $class = shift; return bless { @_ } => $class;}sub as_string { my $self = shift; my ($key, $value, $result); while (($key, $value) = each %$self) { $result .= "$key => $value\n"; } return $result;}$obj = Person->new(height => 72, weight => 165, eyes => "brown");print $obj;</pre></blockquote>Instead of something like <tt class="literal">Person=HASH(0xba1350)</tt>,this prints (in hash order):<blockquote><pre class="programlisting">weight => 165height => 72eyes => brown</pre></blockquote>(We sincerely hope this person was not measured in kg and cm.)</p></dd><dt><b><em class="emphasis">Arithmetic operators:</em><tt class="literal">+</tt><em class="emphasis">,</em><tt class="literal">-</tt><em class="emphasis">,</em><tt class="literal">*</tt><em class="emphasis">,</em><tt class="literal">/</tt><em class="emphasis">,</em><tt class="literal">%</tt><em class="emphasis">,</em><tt class="literal">**</tt><em class="emphasis">,</em><tt class="literal">x</tt><em class="emphasis">,</em><tt class="literal">.</tt><em class="emphasis">,</em><tt class="literal">neg</tt></b></dt><dd><p><a name="INDEX-"></a><a name="INDEX-"></a>These should all be familiar except for <tt class="literal">neg</tt>, whichis a special overloading key for the unary minus: the<tt class="literal">-</tt> in <tt class="literal">-123</tt>. The distinctionbetween the <tt class="literal">neg</tt> and <tt class="literal">-</tt> keysallows you to specify different behaviors for unary minus and binaryminus, more commonly known as subtraction.</p><p><a name="INDEX-"></a><a name="INDEX-"></a><a name="INDEX-"></a>If you overload <tt class="literal">-</tt> but not <tt class="literal">neg</tt>,and then try to use a unary minus, Perl will emulate a<tt class="literal">neg</tt> handler for you. This is known as<em class="emphasis">autogeneration</em>, where certain operators can bereasonably deduced from other operators (on the assumption that theoverloaded operators will have the same relationships as the regularoperators). Since unary minus can be expressed as a function ofbinary minus (that is, <tt class="literal">-123</tt> is equivalent to<tt class="literal">0 - 123</tt>), Perl doesn't force you to overload<tt class="literal">neg</tt> when <tt class="literal">-</tt> will do. (Of course,if you've arbitrarily defined binary minus to divide the secondargument by the first, unary minus will be a fine way to throw adivide-by-0 exception.)</p><p><a name="INDEX-"></a><a name="INDEX-"></a>Concatenation via the <tt class="literal">.</tt> operator can beautogenerated via the stringification handler (see<tt class="literal">""</tt> above).</p></dd><dt><b><em class="emphasis">Logical operator:</em><tt class="literal">!</tt></b></dt><dd><p>If a handler for <tt class="literal">!</tt> is not specified, it can beautogenerated using the <tt class="literal">bool</tt>,<tt class="literal">""</tt>, or <tt class="literal">0+</tt> handler. If youoverload the <tt class="literal">!</tt> operator, the <tt class="literal">not</tt>operator will also trigger whatever behavior you requested. (Rememberour little secret?)<a name="INDEX-"></a><a name="INDEX-"></a><a name="INDEX-"></a><a name="INDEX-"></a></p><p><a name="INDEX-"></a>You may be surprised at the absence of the other logical operators, butmost logical operators can't be overloaded because they short-circuit.They're really control-flow operators that need to be able to delayevaluation of some of their arguments. That's also the reason the<tt class="literal">?:</tt> operator isn't overloaded.</p></dd><dt><b><em class="emphasis">Bitwise operators:</em> <tt class="literal">&</tt><em class="emphasis">,</em> <tt class="literal">|</tt><em class="emphasis">,</em> <tt class="literal">~</tt><em class="emphasis">,</em> <tt class="literal">^</tt><em class="emphasis">,</em> <tt class="literal"><<</tt><em class="emphasis">,</em> <tt class="literal">>></tt></b></dt><dd><p><a name="INDEX-"></a><a name="INDEX-"></a>The <tt class="literal">~</tt> operator is a unary operator; all the others
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -