make gitbook

This commit is contained in:
numbbbbb
2014-06-13 12:35:12 +08:00
parent aac02aab21
commit 01663b6fb0
41 changed files with 767 additions and 657 deletions

View File

@ -46,7 +46,7 @@
<div class="book" data-level="2.23" data-basepath=".." data-revision="1402617910282">
<div class="book" data-level="2.23" data-basepath=".." data-revision="1402634093001">
<div class="book-header">
<!-- Actions Left -->
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
@ -615,32 +615,36 @@
<p>按位取反运算符<code>~</code>对一个操作数的每一位都取反。</p>
<p><img src="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/bitwiseNOT_2x.png" alt="Art/bitwiseNOT_2x.png" title="Art/bitwiseNOT_2x.png"></p>
<p>这个运算符是前置的,所以请不加任何空格地写着操作数之前。</p>
<pre><code>let initialBits: UInt8 = 0b00001111
<pre><code class="lang-swift">let initialBits: UInt8 = 0b00001111
let invertedBits = ~initialBits // 等于 0b11110000
</code></pre><p><code>UInt8</code>是8位无符整型可以存储0~255之间的任意数。这个例子初始化一个整型为二进制值<code>00001111</code>(前4位为<code>0</code>后4位为<code>1</code>),它的十进制值为<code>15</code></p>
</code></pre>
<p><code>UInt8</code>是8位无符整型可以存储0~255之间的任意数。这个例子初始化一个整型为二进制值<code>00001111</code>(前4位为<code>0</code>后4位为<code>1</code>),它的十进制值为<code>15</code></p>
<p>使用按位取反运算<code>~</code><code>initialBits</code>操作,然后赋值给<code>invertedBits</code>这个新常量。这个新常量的值等于所有位都取反的<code>initialBits</code>,即<code>1</code>变成<code>0</code><code>0</code>变成<code>1</code>,变成了<code>11110000</code>,十进制值为<code>240</code></p>
<h3 id="-">按位与运算符</h3>
<p>按位与运算符对两个数进行操作然后返回一个新的数这个数的每个位都需要两个输入数的同一位都为1时才为1。</p>
<p><img src="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/bitwiseAND_2x.png" alt="Art/bitwiseAND_2x.png" title="Art/bitwiseAND_2x.png"></p>
<p>以下代码,<code>firstSixBits</code><code>lastSixBits</code>中间4个位都为1。对它俩进行按位与运算后就得到了<code>00111100</code>,即十进制的<code>60</code></p>
<pre><code>let firstSixBits: UInt8 = 0b11111100
<pre><code class="lang-swift">let firstSixBits: UInt8 = 0b11111100
let lastSixBits: UInt8 = 0b00111111
let middleFourBits = firstSixBits &amp; lastSixBits // 等于 00111100
</code></pre><h3 id="-">按位或运算</h3>
</code></pre>
<h3 id="-">按位或运算</h3>
<p>按位或运算符<code>|</code>比较两个数然后返回一个新的数这个数的每一位设置1的条件是两个输入数的同一位都不为0(即任意一个为1或都为1)。</p>
<p><img src="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/bitwiseOR_2x.png" alt="Art/bitwiseOR_2x.png" title="Art/bitwiseOR_2x.png"></p>
<p>如下代码,<code>someBits</code><code>moreBits</code>在不同位上有<code>1</code>。按位或运行的结果是<code>11111110</code>,即十进制的<code>254</code></p>
<pre><code>let someBits: UInt8 = 0b10110010
<pre><code class="lang-swift">let someBits: UInt8 = 0b10110010
let moreBits: UInt8 = 0b01011110
let combinedbits = someBits | moreBits // 等于 11111110
</code></pre><h3 id="-">按位异或运算符</h3>
</code></pre>
<h3 id="-">按位异或运算符</h3>
<p>按位异或运算符<code>^</code>比较两个数,然后返回一个数,这个数的每个位设为<code>1</code>的条件是两个输入数的同一位不同,如果相同就设为<code>0</code></p>
<p><img src="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/bitwiseXOR_2x.png" alt="Art/bitwiseXOR_2x.png" title="Art/bitwiseXOR_2x.png"></p>
<p>以下代码,<code>firstBits</code><code>otherBits</code>都有一个<code>1</code>跟另一个数不同的。所以按位异或的结果是把它这些位置为<code>1</code>,其他都置为<code>0</code></p>
<pre><code>let firstBits: UInt8 = 0b00010100
<pre><code class="lang-swift">let firstBits: UInt8 = 0b00010100
let otherBits: UInt8 = 0b00000101
let outputBits = firstBits ^ otherBits // 等于 00010001
</code></pre><h3 id="-">按位左移/右移运算符</h3>
</code></pre>
<h3 id="-">按位左移/右移运算符</h3>
<p>左移运算符<code>&lt;&lt;</code>和右移运算符<code>&gt;&gt;</code>会把一个数的所有比特位按以下定义的规则向左或向右移动指定位数。</p>
<p>按位左移和按位右移的效果相当把一个整数乘于或除于一个因子为<code>2</code>的整数。向左移动一个整型的比特位相当于把这个数乘于<code>2</code>,向右移一位就是除于<code>2</code></p>
<h4 id="-">无符整型的移位操作</h4>
@ -648,18 +652,20 @@ let outputBits = firstBits ^ otherBits // 等于 00010001
<p>已经存在的比特位向左或向右移动指定的位数。被移出整型存储边界的的位数直接抛弃,移动留下的空白位用零<code>0</code>来填充。这种方法称为逻辑移位。</p>
<p>以下这张把展示了 <code>11111111 &lt;&lt; 1</code>(<code>11111111</code>向左移1位),和 <code>11111111 &gt;&gt; 1</code>(<code>11111111</code>向右移1位)。蓝色的是被移位的,灰色是被抛弃的,橙色的<code>0</code>是被填充进来的。</p>
<p><img src="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/bitshiftUnsigned_2x.png" alt="Art/bitshiftUnsigned_2x.png" title="Art/bitshiftUnsigned_2x.png"></p>
<pre><code>let shiftBits: UInt8 = 4 // 即二进制的00000100
<pre><code class="lang-swift">let shiftBits: UInt8 = 4 // 即二进制的00000100
shiftBits &lt;&lt; 1 // 00001000
shiftBits &lt;&lt; 2 // 00010000
shiftBits &lt;&lt; 5 // 10000000
shiftBits &lt;&lt; 6 // 00000000
shiftBits &gt;&gt; 2 // 00000001
</code></pre><p>你可以使用移位操作进行其他数据类型的编码和解码。</p>
<pre><code>let pink: UInt32 = 0xCC6699
</code></pre>
<p>你可以使用移位操作进行其他数据类型的编码和解码。</p>
<pre><code class="lang-swift">let pink: UInt32 = 0xCC6699
let redComponent = (pink &amp; 0xFF0000) &gt;&gt; 16 // redComponent 是 0xCC, 即 204
let greenComponent = (pink &amp; 0x00FF00) &gt;&gt; 8 // greenComponent 是 0x66, 即 102
let blueComponent = pink &amp; 0x0000FF // blueComponent 是 0x99, 即 153
</code></pre><p>这个例子使用了一个<code>UInt32</code>的命名为<code>pink</code>的常量来存储层叠样式表<code>CSS</code>中粉色的颜色值,<code>CSS</code>颜色<code>#CC6699</code>在Swift用十六进制<code>0xCC6699</code>来表示。然后使用按位与(&amp;)和按位右移就可以从这个颜色值中解析出红(CC),绿(66),蓝(99)三个部分。</p>
</code></pre>
<p>这个例子使用了一个<code>UInt32</code>的命名为<code>pink</code>的常量来存储层叠样式表<code>CSS</code>中粉色的颜色值,<code>CSS</code>颜色<code>#CC6699</code>在Swift用十六进制<code>0xCC6699</code>来表示。然后使用按位与(&amp;)和按位右移就可以从这个颜色值中解析出红(CC),绿(66),蓝(99)三个部分。</p>
<p><code>0xCC6699</code><code>0xFF0000</code>进行按位与<code>&amp;</code>操作就可以得到红色部分。<code>0xFF0000</code>中的<code>0</code>了遮盖了<code>OxCC6699</code>的第二和第三个字节,这样<code>6699</code>被忽略了,只留下<code>0xCC0000</code></p>
<p>然后按向右移动16位<code>&gt;&gt; 16</code>。十六进制中每两个字符是8比特位所以移动16位的结果是把<code>0xCC0000</code>变成<code>0x0000CC</code>。这和<code>0xCC</code>是相等的,都是十进制的<code>204</code></p>
<p>同样的,绿色部分来自于<code>0xCC6699</code><code>0x00FF00</code>的按位操作得到<code>0x006600</code>。然后向右移动8們得到<code>0x66</code>,即十进制的<code>102</code></p>
@ -687,11 +693,12 @@ let blueComponent = pink &amp; 0x0000FF // blueComponent 是 0x99, 即
<h2 id="-">溢出运算符</h2>
<p>默认情况下当你往一个整型常量或变量赋于一个它不能承载的大数时Swift不会让你这么干的它会报错。这样在操作过大或过小的数的时候就很安全了。</p>
<p>例如,<code>Int16</code>整型能承载的整数范围是<code>-32768</code><code>32767</code>,如果给它赋上超过这个范围的数,就会报错:</p>
<pre><code>var potentialOverflow = Int16.max
<pre><code class="lang-swift">var potentialOverflow = Int16.max
// potentialOverflow 等于 32767, 这是 Int16 能承载的最大整数
potentialOverflow += 1
// 噢, 出错了
</code></pre><p>对过大或过小的数值进行错误处理让你的数值边界条件更灵活。</p>
</code></pre>
<p>对过大或过小的数值进行错误处理让你的数值边界条件更灵活。</p>
<p>当然你有意在溢出时对有效位进行截断你可采用溢出运算而非错误处理。Swfit为整型计算提供了5个<code>&amp;</code>符号开头的溢出运算符。</p>
<ul>
<li>溢出加法 <code>&amp;+</code></li>
@ -702,44 +709,50 @@ potentialOverflow += 1
</ul>
<h3 id="-">值的上溢出</h3>
<p>下面例子使用了溢出加法<code>&amp;+</code>来解剖的无符整数的上溢出</p>
<pre><code>var willOverflow = UInt8.max
<pre><code class="lang-swift">var willOverflow = UInt8.max
// willOverflow 等于UInt8的最大整数 255
willOverflow = willOverflow &amp;+ 1
// 这时候 willOverflow 等于 0
</code></pre><p><code>willOverflow</code><code>Int8</code>所能承载的最大值<code>255</code>(二进制<code>11111111</code>),然后用<code>&amp;+</code>加1。然后<code>UInt8</code>就无法表达这个新值的二进制了,也就导致了这个新值上溢出了,大家可以看下图。溢出后,新值在<code>UInt8</code>的承载范围内的那部分是<code>00000000</code>,也就是<code>0</code></p>
</code></pre>
<p><code>willOverflow</code><code>Int8</code>所能承载的最大值<code>255</code>(二进制<code>11111111</code>),然后用<code>&amp;+</code>加1。然后<code>UInt8</code>就无法表达这个新值的二进制了,也就导致了这个新值上溢出了,大家可以看下图。溢出后,新值在<code>UInt8</code>的承载范围内的那部分是<code>00000000</code>,也就是<code>0</code></p>
<p><img src="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/overflowAddition_2x.png" alt="Art/overflowAddition_2x.png" title="Art/overflowAddition_2x.png"></p>
<h3 id="-">值的下溢出</h3>
<p>数值也有可能因为太小而越界。举个例子:</p>
<p><code>UInt8</code>的最小值是<code>0</code>(二进制为<code>00000000</code>)。使用<code>&amp;-</code>进行溢出减1就会得到二进制的<code>11111111</code>即十进制的<code>255</code></p>
<p><img src="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/overflowUnsignedSubtraction_2x.png" alt="Art/overflowUnsignedSubtraction_2x.png" title="Art/overflowUnsignedSubtraction_2x.png"></p>
<p>Swift代码是这样的:</p>
<pre><code>var willUnderflow = UInt8.min
<pre><code class="lang-swift">var willUnderflow = UInt8.min
// willUnderflow 等于UInt8的最小值0
willUnderflow = willUnderflow &amp;- 1
// 此时 willUnderflow 等于 255
</code></pre><p>有符整型也有类似的下溢出,有符整型所有的减法也都是对包括在符号位在内的二进制数进行二进制减法的,这在 &quot;按位左移/右移运算符&quot; 一节提到过。最小的有符整数是<code>-128</code>,即二进制的<code>10000000</code>。用溢出减法减去去1后变成了<code>01111111</code>即UInt8所能承载的最大整数<code>127</code></p>
</code></pre>
<p>有符整型也有类似的下溢出,有符整型所有的减法也都是对包括在符号位在内的二进制数进行二进制减法的,这在 &quot;按位左移/右移运算符&quot; 一节提到过。最小的有符整数是<code>-128</code>,即二进制的<code>10000000</code>。用溢出减法减去去1后变成了<code>01111111</code>即UInt8所能承载的最大整数<code>127</code></p>
<p><img src="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/overflowSignedSubtraction_2x.png" alt="Art/overflowSignedSubtraction_2x.png" title="Art/overflowSignedSubtraction_2x.png"></p>
<p>来看看Swift代码</p>
<pre><code>var signedUnderflow = Int8.min
<pre><code class="lang-swift">var signedUnderflow = Int8.min
// signedUnderflow 等于最小的有符整数 -128
signedUnderflow = signedUnderflow &amp;- 1
// 如今 signedUnderflow 等于 127
</code></pre><h3 id="-">除零溢出</h3>
</code></pre>
<h3 id="-">除零溢出</h3>
<p>一个数除于0 <code>i / 0</code>或者对0求余数 <code>i % 0</code>,就会产生一个错误。</p>
<pre><code>let x = 1
<pre><code class="lang-swift">let x = 1
let y = x / 0
</code></pre><p>使用它们对应的可溢出的版本的运算符<code>&amp;/</code><code>&amp;%</code>进行除0操作时就会得到<code>0</code>值。</p>
<pre><code>let x = 1
</code></pre>
<p>使用它们对应的可溢出的版本的运算符<code>&amp;/</code><code>&amp;%</code>进行除0操作时就会得到<code>0</code>值。</p>
<pre><code class="lang-swift">let x = 1
let y = x &amp;/ 0
// y 等于 0
</code></pre><p><a name="precedence_and_associativity"></a></p>
</code></pre>
<p><a name="precedence_and_associativity"></a></p>
<h2 id="-">优先级和结合性</h2>
<p>运算符的优先级使得一些运算符优先于其他运算符,高优先级的运算符会先被计算。</p>
<p>结合性定义相同优先级的运算符在一起时是怎么组合或关联的,是和左边的一组呢,还是和右边的一组。意思就是,到底是和左边的表达式结合呢,还是和右边的表达式结合?</p>
<p>在混合表达式中,运算符的优先级和结合性是非常重要的。举个例子,为什么下列表达式的结果为<code>4</code></p>
<pre><code>2 + 3 * 4 % 5
<pre><code class="lang-swift">2 + 3 * 4 % 5
// 结果是 4
</code></pre><p>如果严格地从左计算到右,计算过程会是这样:</p>
</code></pre>
<p>如果严格地从左计算到右,计算过程会是这样:</p>
<ul>
<li>2 plus 3 equals 5;</li>
<li>2 + 3 = 5</li>
@ -750,14 +763,17 @@ let y = x &amp;/ 0
</ul>
<p>但是正确答案是<code>4</code>而不是<code>0</code>。优先级高的运算符要先计算在Swift和C语言中都是先乘除后加减的。所以执行完乘法和求余运算才能执行加减运算。</p>
<p>乘法和求余拥有相同的优先级,在运算过程中,我们还需要结合性,乘法和求余运算都是左结合的。这相当于在表达式中有隐藏的括号让运算从左开始。</p>
<pre><code>2 + ((3 * 4) % 5)
</code></pre><p>(3 <em> 4) is 12, so this is equivalent to:
<pre><code class="lang-swift">2 + ((3 * 4) % 5)
</code></pre>
<p>(3 <em> 4) is 12, so this is equivalent to:
3 </em> 4 = 12所以这相当于</p>
<pre><code>2 + (12 % 5)
</code></pre><p>(12 % 5) is 2, so this is equivalent to:
<pre><code class="lang-swift">2 + (12 % 5)
</code></pre>
<p>(12 % 5) is 2, so this is equivalent to:
12 % 5 = 2所这又相当于</p>
<pre><code>2 + 2
</code></pre><p>计算结果为 4。</p>
<pre><code class="lang-swift">2 + 2
</code></pre>
<p>计算结果为 4。</p>
<p>查阅Swift运算符的优先级和结合性的完整列表请看<a href="../chapter3/04_Expressions.html">表达式</a></p>
<blockquote>
<p>注意:</p>
@ -768,96 +784,109 @@ let y = x &amp;/ 0
<p>让已有的运算符也可以对自定义的类和结构进行运算,这称为运算符重载。</p>
<p>这个例子展示了如何用<code>+</code>让一个自定义的结构做加法。算术运算符<code>+</code>是一个两目运算符,因为它有两个操作数,而且它必须出现在两个操作数之间。</p>
<p>例子中定义了一个名为<code>Vector2D</code>的二维坐标向量 <code>(xy)</code> 的结构,然后定义了让两个<code>Vector2D</code>的对象相加的运算符函数。</p>
<pre><code>struct Vector2D {
<pre><code class="lang-swift">struct Vector2D {
var x = 0.0, y = 0.0
}
@infix func + (left: Vector2D, right: Vector2D) -&gt; Vector2D {
return Vector2D(x: left.x + right.x, y: left.y + right.y)
}
</code></pre><p>该运算符函数定义了一个全局的<code>+</code>函数,这个函数需要两个<code>Vector2D</code>类型的参数,返回值也是<code>Vector2D</code>类型。需要定义和实现一个中置运算的时候,在关键字<code>func</code>之前写上属性 <code>@infix</code> 就可以了。</p>
</code></pre>
<p>该运算符函数定义了一个全局的<code>+</code>函数,这个函数需要两个<code>Vector2D</code>类型的参数,返回值也是<code>Vector2D</code>类型。需要定义和实现一个中置运算的时候,在关键字<code>func</code>之前写上属性 <code>@infix</code> 就可以了。</p>
<p>在这个代码实现中,参数被命名为了<code>left</code><code>right</code>,代表<code>+</code>左边和右边的两个<code>Vector2D</code>对象。函数返回了一个新的<code>Vector2D</code>的对象,这个对象的<code>x</code><code>y</code>分别等于两个参数对象的<code>x</code><code>y</code>的和。</p>
<p>这个函数是全局的,而不是<code>Vector2D</code>结构的成员方法,所以任意两个<code>Vector2D</code>对象都可以使用这个中置运算符。</p>
<pre><code>let vector = Vector2D(x: 3.0, y: 1.0)
<pre><code class="lang-swift">let vector = Vector2D(x: 3.0, y: 1.0)
let anotherVector = Vector2D(x: 2.0, y: 4.0)
let combinedVector = vector + anotherVector
// combinedVector 是一个新的Vector2D, 值为 (5.0, 5.0)
</code></pre><p>这个例子实现两个向量 <code>(3.01.0)</code><code>(2.04.0)</code> 相加,得到向量 <code>(5.05.0)</code> 的过程。如下图示:</p>
</code></pre>
<p>这个例子实现两个向量 <code>(3.01.0)</code><code>(2.04.0)</code> 相加,得到向量 <code>(5.05.0)</code> 的过程。如下图示:</p>
<p><img src="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/vectorAddition_2x.png" alt="Art/vectorAddition_2x.png" title="Art/vectorAddition_2x.png"></p>
<h3 id="-">前置和后置运算符</h3>
<p>上个例子演示了一个双目中置运算符的自定义实现,同样我们也可以玩标准单目运算符的实现。单目运算符只有一个操作数,在操作数之前就是前置的,如<code>-a</code>; 在操作数之后就是后置的,如<code>i++</code></p>
<p>实现一个前置或后置运算符时,在定义该运算符的时候于关键字<code>func</code>之前标注 <code>@prefix</code><code>@postfix</code> 属性。</p>
<pre><code>@prefix func - (vector: Vector2D) -&gt; Vector2D {
<pre><code class="lang-swift">@prefix func - (vector: Vector2D) -&gt; Vector2D {
return Vector2D(x: -vector.x, y: -vector.y)
}
</code></pre><p>这段代码为<code>Vector2D</code>类型提供了单目减运算<code>-a</code><code>@prefix</code>属性表明这是个前置运算符。</p>
</code></pre>
<p>这段代码为<code>Vector2D</code>类型提供了单目减运算<code>-a</code><code>@prefix</code>属性表明这是个前置运算符。</p>
<p>对于数值,单目减运算符可以把正数变负数,把负数变正数。对于<code>Vector2D</code>,单目减运算将其<code>x</code><code>y</code>都进进行单目减运算。</p>
<pre><code>let positive = Vector2D(x: 3.0, y: 4.0)
<pre><code class="lang-swift">let positive = Vector2D(x: 3.0, y: 4.0)
let negative = -positive
// negative 为 (-3.0, -4.0)
let alsoPositive = -negative
// alsoPositive 为 (3.0, 4.0)
</code></pre><h3 id="-">组合赋值运算符</h3>
</code></pre>
<h3 id="-">组合赋值运算符</h3>
<p>组合赋值是其他运算符和赋值运算符一起执行的运算。如<code>+=</code>把加运算和赋值运算组合成一个操作。实现一个组合赋值符号需要使用<code>@assignment</code>属性,还需要把运算符的左参数设置成<code>inout</code>,因为这个参数会在运算符函数内直接修改它的值。</p>
<pre><code>@assignment func += (inout left: Vector2D, right: Vector2D) {
<pre><code class="lang-swift">@assignment func += (inout left: Vector2D, right: Vector2D) {
left = left + right
}
</code></pre><p>因为加法运算在之前定义过了,这里无需重新定义。所以,加赋运算符函数使用已经存在的高级加法运算符函数来执行左值加右值的运算。</p>
<pre><code>var original = Vector2D(x: 1.0, y: 2.0)
</code></pre>
<p>因为加法运算在之前定义过了,这里无需重新定义。所以,加赋运算符函数使用已经存在的高级加法运算符函数来执行左值加右值的运算。</p>
<pre><code class="lang-swift">var original = Vector2D(x: 1.0, y: 2.0)
let vectorToAdd = Vector2D(x: 3.0, y: 4.0)
original += vectorToAdd
// original 现在为 (4.0, 6.0)
</code></pre><p>你可以将 <code>@assignment</code> 属性和 <code>@prefix</code><code>@postfix</code> 属性起来组合,实现一个<code>Vector2D</code>的前置运算符。</p>
<pre><code>@prefix @assignment func ++ (inout vector: Vector2D) -&gt; Vector2D {
</code></pre>
<p>你可以将 <code>@assignment</code> 属性和 <code>@prefix</code><code>@postfix</code> 属性起来组合,实现一个<code>Vector2D</code>的前置运算符。</p>
<pre><code class="lang-swift">@prefix @assignment func ++ (inout vector: Vector2D) -&gt; Vector2D {
vector += Vector2D(x: 1.0, y: 1.0)
return vector
}
</code></pre><p>这个前置使用了已经定义好的高级加赋运算,将自己加上一个值为 <code>(1.01.0)</code> 的对象然后赋给自己,然后再将自己返回。</p>
<pre><code>var toIncrement = Vector2D(x: 3.0, y: 4.0)
</code></pre>
<p>这个前置使用了已经定义好的高级加赋运算,将自己加上一个值为 <code>(1.01.0)</code> 的对象然后赋给自己,然后再将自己返回。</p>
<pre><code class="lang-swift">var toIncrement = Vector2D(x: 3.0, y: 4.0)
let afterIncrement = ++toIncrement
// toIncrement 现在是 (4.0, 5.0)
// afterIncrement 现在也是 (4.0, 5.0)
</code></pre><blockquote>
</code></pre>
<blockquote>
<p>注意:</p>
<p>默认的赋值符是不可重载的。只有组合赋值符可以重载。三目条件运算符 <code>abc</code> 也是不可重载。</p>
</blockquote>
<h3 id="-">比较运算符</h3>
<p>Swift无所知道自定义类型是否相等或不等因为等于或者不等于由你的代码说了算了。所以自定义的类和结构要使用比较符<code>==</code><code>!=</code>就需要重载。</p>
<p>定义相等运算符函数跟定义其他中置运算符雷同:</p>
<pre><code>@infix func == (left: Vector2D, right: Vector2D) -&gt; Bool {
<pre><code class="lang-swift">@infix func == (left: Vector2D, right: Vector2D) -&gt; Bool {
return (left.x == right.x) &amp;&amp; (left.y == right.y)
}
@infix func != (left: Vector2D, right: Vector2D) -&gt; Bool {
return !(left == right)
}
</code></pre><p>上述代码实现了相等运算符<code>==</code>来判断两个<code>Vector2D</code>对象是否有相等的值,相等的概念就是他们有相同的<code>x</code>值和相同的<code>y</code>值,我们就用这个逻辑来实现。接着使用<code>==</code>的结果实现了不相等运算符<code>!=</code></p>
</code></pre>
<p>上述代码实现了相等运算符<code>==</code>来判断两个<code>Vector2D</code>对象是否有相等的值,相等的概念就是他们有相同的<code>x</code>值和相同的<code>y</code>值,我们就用这个逻辑来实现。接着使用<code>==</code>的结果实现了不相等运算符<code>!=</code></p>
<p>现在我们可以使用这两个运算符来判断两个<code>Vector2D</code>对象是否相等。</p>
<pre><code>let twoThree = Vector2D(x: 2.0, y: 3.0)
<pre><code class="lang-swift">let twoThree = Vector2D(x: 2.0, y: 3.0)
let anotherTwoThree = Vector2D(x: 2.0, y: 3.0)
if twoThree == anotherTwoThree {
println(&quot;这两个向量是相等的.&quot;)
}
// prints &quot;这两个向量是相等的.&quot;
</code></pre><h3 id="-">自定义运算符</h3>
</code></pre>
<h3 id="-">自定义运算符</h3>
<p>标准的运算符不够玩,那你可以声明一些个性的运算符,但个性的运算符只能使用这些字符 <code>/ = - + * % &lt; &gt;&amp; | ^。~</code></p>
<p>新的运算符声明需在全局域使用<code>operator</code>关键字声明,可以声明为前置,中置或后置的。</p>
<pre><code>operator prefix +++ {}
</code></pre><p>这段代码定义了一个新的前置运算符叫<code>+++</code>此前Swift并不存在这个运算符。此处为了演示我们让<code>+++</code><code>Vector2D</code>对象的操作定义为 <code>双自增</code> 这样一个独有的操作,这个操作使用了之前定义的加赋运算实现了自已加上自己然后返回的运算。</p>
<pre><code>@prefix @assignment func +++ (inout vector: Vector2D) -&gt; Vector2D {
<pre><code class="lang-swift">operator prefix +++ {}
</code></pre>
<p>这段代码定义了一个新的前置运算符叫<code>+++</code>此前Swift并不存在这个运算符。此处为了演示我们让<code>+++</code><code>Vector2D</code>对象的操作定义为 <code>双自增</code> 这样一个独有的操作,这个操作使用了之前定义的加赋运算实现了自已加上自己然后返回的运算。</p>
<pre><code class="lang-swift">@prefix @assignment func +++ (inout vector: Vector2D) -&gt; Vector2D {
vector += vector
return vector
}
</code></pre><p><code>Vector2D</code><code>+++</code> 的实现和 <code>++</code> 的实现很接近, 唯一不同的前者是加自己, 后者是加值为 <code>(1.0, 1.0)</code> 的向量.</p>
<pre><code>var toBeDoubled = Vector2D(x: 1.0, y: 4.0)
</code></pre>
<p><code>Vector2D</code><code>+++</code> 的实现和 <code>++</code> 的实现很接近, 唯一不同的前者是加自己, 后者是加值为 <code>(1.0, 1.0)</code> 的向量.</p>
<pre><code class="lang-swift">var toBeDoubled = Vector2D(x: 1.0, y: 4.0)
let afterDoubling = +++toBeDoubled
// toBeDoubled 现在是 (2.0, 8.0)
// afterDoubling 现在也是 (2.0, 8.0)
</code></pre><h3 id="-">自定义中置运算符的优先级和结合性</h3>
</code></pre>
<h3 id="-">自定义中置运算符的优先级和结合性</h3>
<p>可以为自定义的中置运算符指定优先级和结合性。可以回头看看<a href="#PrecedenceandAssociativity">优先级和结合性</a>解释这两个因素是如何影响多种中置运算符混合的表达式的计算的。</p>
<p>结合性(associativity)的值可取的值有<code>left</code><code>right</code><code>none</code>。左结合运算符跟其他优先级相同的左结合运算符写在一起时,会跟左边的操作数结合。同理,右结合运算符会跟右边的操作数结合。而非结合运算符不能跟其他相同优先级的运算符写在一起。</p>
<p>结合性(associativity)的值默认为<code>none</code>,优先级(precedence)默认为<code>100</code></p>
<p>以下例子定义了一个新的中置符<code>+-</code>,是左结合的<code>left</code>,优先级为<code>140</code></p>
<pre><code>operator infix +- { associativity left precedence 140 }
<pre><code class="lang-swift">operator infix +- { associativity left precedence 140 }
func +- (left: Vector2D, right: Vector2D) -&gt; Vector2D {
return Vector2D(x: left.x + right.x, y: left.y - right.y)
}
@ -865,7 +894,8 @@ let firstVector = Vector2D(x: 1.0, y: 2.0)
let secondVector = Vector2D(x: 3.0, y: 4.0)
let plusMinusVector = firstVector +- secondVector
// plusMinusVector 此时的值为 (4.0, -2.0)
</code></pre><p>这个运算符把两个向量的<code>x</code>相加,把向量的<code>y</code>相减。因为他实际是属于加减运算,所以让它保持了和加法一样的结合性和优先级(<code>left</code><code>140</code>)。查阅完整的Swift默认结合性和优先级的设置请移步<a href="../chapter3/04_Expressions.html">表达式</a>;</p>
</code></pre>
<p>这个运算符把两个向量的<code>x</code>相加,把向量的<code>y</code>相减。因为他实际是属于加减运算,所以让它保持了和加法一样的结合性和优先级(<code>left</code><code>140</code>)。查阅完整的Swift默认结合性和优先级的设置请移步<a href="../chapter3/04_Expressions.html">表达式</a>;</p>
</section>