Swift語法總結(jié)2.25(高級運算符)

高級運算符(Advanced Operators)

本文參考自蘋果官方文檔Advanced Operators
本頁內(nèi)容包括

  • 位運算符(Bitwise Operators)
  • 溢出運算符(Overflow Operators)
  • 優(yōu)先級和結(jié)合性(Precedence and Associativity)
  • 運算符函數(shù)(Operator Functions)
  • 自定義運算符(Custom Operators)

除了在基本運算符(Basic Operator)中介紹的運算符外,Swift提供一些對值進行復(fù)雜操作的高級運算符
這些高級運算符包含在C和Objective-C中大家所熟知的位運算符和移位運算符。

與C語言中的算術(shù)運算符不同的是,Swift中的算術(shù)運算符默認不溢出.
溢出行為都會被捕獲并報告為錯誤.
如果要允許溢出行為,可以使用Swift中第二套默認支持溢出的運算符,比如溢出加法運算符(&+).
所有的這些溢出運算符都是以&開頭

當(dāng)你自定義結(jié)構(gòu)體,類和枚舉時,為它們提供對標(biāo)準的Swift運算符自定義實現(xiàn)將會非常有用.
在Swift中為這些運算符提供定制的實現(xiàn)和為每一種你創(chuàng)建的類型決定運算符的行為都是很簡單的.

你不會被預(yù)定義的運算符所限制.
**Swift給予你用自定義優(yōu)先級和結(jié)合性來自定義前綴/中綴/后綴/賦值運算符的自由. **
這些運算符在代碼中可以像任意預(yù)定義的運算符一樣被使用,我們甚至可以擴展已有的類型以支持你自定義的運算符进统。

位運算符(Bitwise Operators)

位運算符使你可以操作數(shù)據(jù)結(jié)構(gòu)中獨立的原始的. 它們通常被用在底層開發(fā)中,比如圖形編程和創(chuàng)建設(shè)備驅(qū)動.位運算符在處理外部資源的原始數(shù)據(jù)時也十分有用,比如對自定義協(xié)議的通信傳輸?shù)臄?shù)據(jù)進行編碼和解碼。

Swift支持如下所述的C語言中的全部位運算符

按位取反運算符

按位取反運算符(~)可以對一個數(shù)值的全部位進行取反:

bitwiseNOT.png

按位取反運算符是一個前綴運算符,出現(xiàn)在被操作數(shù)之前,之間不能添加任何空格:
<pre><code>let initialBits : UInt8 = 0b00001111 let invertedBits = ~initialBits//等于0b11110000</code></pre>

UInt8類型的整數(shù)有8個位,可以存儲0~255之間的任意值.這個例子用二進制的值00001111初始化了一個UInt8類型的整數(shù),它的前4位都為0,后4位都為1.這個值等價于十進制的15.

之后用按位取反運算符創(chuàng)建了一個名為invertedBits的常量.其值與全部位取反后的initialBits相等.即所有的0都變成了1,同時所有的1都變成0.invertedBits的二進制值為11110000,等價于無符號十進制的240

按位與運算符

按位與運算符(&)可以對兩個數(shù)的位進行合并.它返回一個新的數(shù),其位會被設(shè)置為1,只有當(dāng)兩個數(shù)的位都為1時.

bitwiseAND.png

在下例中,firstSixBits和lastSixBits中間4個位都為1.按位與運算符對它們進行了運算得到數(shù)00111100,等價于無符號十進制數(shù)60:
<pre><code>let firstSixBits: UInt8 = 0b11111100 let lastSixBits: UInt8 = 0b00111111 let middleFourBits = firstSixBits & lastSixBits //等于00111100</code></pre>

按位或運算符

按位或運算符(|)對兩個數(shù)的位進行比較.它返回一個新的數(shù),其位被設(shè)置為1,如果任意一個數(shù)的位為1.

bitwiseOR.png

在下例中,按位或運算符對someBits和moreBits進行了運算得到數(shù)11111110,等價于無符號十進制數(shù)254:
<pre><code>let someBits: UInt8 = 0b10110010 let moreBits: UInt8 = 0b01011110 let combinedbits = someBits | moreBits //等于11111110</code></pre>

按位異或運算符

按位異或運算符(^)對兩個數(shù)的位進行比較.它返回一個新的數(shù),其位被設(shè)置為1當(dāng)兩個數(shù)的位不相同時,其位被設(shè)置為0當(dāng)兩個數(shù)的位相同時.

bitwiseXOR.png

在下例中,firstBits和otherBits都有一個位得值為1而另一個對應(yīng)的不是1.按位異或運算符將結(jié)果中的這兩個位都設(shè)置為1,將其它位設(shè)置為0:
<pre><code>let firstBits: UInt8 = 0b00010100 let otherBits: UInt8 = 0b00000101 let outputBits = firstBits ^ otherBits // 等于 00010001</code></pre>

按位左移/右移運算符

按位左移運算符(<<)按位右移運算符(>>)可以對一個數(shù)的所有位進行指定位數(shù)的左移和右移,根據(jù)下面定義的規(guī)則

將一個整數(shù)左移一位相當(dāng)于將這個數(shù)乘以2,同樣地將一個整數(shù)右移一位相當(dāng)于將這個數(shù)除以2

無符號整數(shù)的移位運算

對無符號整數(shù)進行移位的規(guī)則如下:

  • 已經(jīng)存在的位按指定的位數(shù)進行左移和右移
  • 任何因移動而超出整型存儲范圍的位都會被丟棄
  • 用0來填充移位后遺留的空白位

這種方法被稱為邏輯移位

下圖展示了11111111 << 1(即把11111111向左移動1位)和 11111111 >> 1(即把 11111111向右移動1位)的結(jié)果.
藍色的部分是被移位的,灰色的部分是被拋棄的,橙色的部分則是被填充進來的:

bitshiftUnsigned.png

這里是Swift中的移位運算:
<pre><code>let shiftBits: UInt8 = 4 // 00000100 shiftBits << 1 // 00001000 shiftBits << 2 // 00010000 shiftBits << 5 // 10000000 shiftBits << 6 // 00000000 shiftBits >> 2 // 00000001</code></pre>

你可以使用移位運算對其他的數(shù)據(jù)類型進行編碼和解碼:
<pre><code>let pink: UInt32 = 0xCC6699 let redComponent = (pink & 0xFF0000) >> 16//redComponent是0xCC,即204 let greenComponent = (pink & 0x00FF00) >> 8//greenComponent是 0x66,即102 let blueComponent = pink & 0x0000FF//blueComponent是0x99,153</code></pre>

這個示例使用了一個命名為pink的UInt32類型型常量來存儲CSS中粉色的顏色值.該CSS顏色值的#CC6699在Swift中的十六進制表示為0xCC6699.用按位與運算符(&)和按位右移運算符(>>)從這個顏色值中分解出紅(CC),綠(66),以及藍(99)三個部分.

紅色部分是通過對0xCC6699和0xFF0000進行按位與運算后得到的.0xFF0000中的0部分“掩蓋”了OxCC6699中的第二,第三個字節(jié),使得數(shù)值中的6699被忽略,只留下0xCC0000作為結(jié)果

然后將這個數(shù)按向右移動16 位(>>16),十六進制中每兩個字符表示8個比特位,所以移動16位后0xCC0000就變?yōu)?x0000CC.這個數(shù)和0xCC是等同的,也就是十進制的204.

類似的,綠色部分通過對0xCC6699和0x00FF00進行按位與運算得到0x006600.然后將這個數(shù)向右移動8位,得到0x66,也就是十進制的102

最后,藍色部分通過對0xCC6699和0x0000FF進行按位與運算得到 0x000099,這里不需要再向右移位,所以結(jié)果為0x99,也就是十進制數(shù)值的153

有符號整數(shù)的移位運算

有符號整數(shù)的移位運算對比無符號整數(shù)相對復(fù)雜得多,這源于有符號整數(shù)的二進制表現(xiàn)形式.(為了簡單起見,以下的示例都是基于8位的有符號整數(shù)的,但是其中的原理對任何位數(shù)的有符號整數(shù)都是通用的)

有符號整數(shù)使用第1個位(通常被稱為符號位)來表示這個數(shù)的正負.符號位為0代表正數(shù),為1代表負數(shù).
其余的位(通常被稱為數(shù)值位)存儲了實際的值.

有符號正整數(shù)和無符號數(shù)的存儲方式是一樣的,都是從0開始算起.
這是值為4的Int8類型型整數(shù)的二進制位表現(xiàn)形式:

bitshiftSignedFour.png

符號位為0說明這是一個正數(shù),另外7個數(shù)值位則代表了十進制數(shù)值4的二進制表示.

然而負數(shù)的存儲方式略有不同.負數(shù)以 2的n次方減去該負數(shù)的絕對值(n為數(shù)值位的位數(shù)) 的方式被存儲.一個8位的數(shù)有7個位是數(shù)值位,所以是2的7次方,即128

這是值為-4的Int8類型整數(shù)的二進制位表現(xiàn)形式:


bitshiftSignedMinusFour.png

這次的符號位為1,(說明這是一個負數(shù)),另外7個數(shù)值位則代表了數(shù)值124(即128 - 4)的二進制表示


bitshiftSignedMinusFourValue.png

負數(shù)的這種編碼通常被稱為二進制補碼.它看起來是一種表示負數(shù)的奇怪方式,但它有幾個優(yōu)點.

首先,你可以對-1和-4進行加法運算,只需要將這兩個數(shù)的全部8個位進行相加(包括符號位),并且計算完成時將超出8位的數(shù)值丟棄:

bitshiftSignedAddition.png

其次,用二進制補碼可以使負數(shù)如同正數(shù)那樣按位左移和右移運算,即每向左移一位就將自身的數(shù)值乘以2,每向右一位就將自身的數(shù)值除以2.要達到此目的,對有符號整數(shù)的右移有一個額外的規(guī)則:
當(dāng)對整數(shù)進行按位右移運算時,遵循與無符號整數(shù)相同的規(guī)則,但是對于移位產(chǎn)生的空白位使用符號位進行填充,而不是用0

bitshiftSigned.png

這個行為可以確保有符號整數(shù)在右移運算后符號位不會改變
這被稱為算術(shù)移位

由于正數(shù)和負數(shù)的特殊存儲方式,在對它們進行右移的時候,會使它們越來越接近0.
在移位的過程中保持符號位不變,意味著負整數(shù)在接近0的過程中會一直保持為負

溢出運算符(Overflow Operators)

如果你嘗試為一個整數(shù)類型常量或變量賦予超過其承載范圍的值,Swift默認會報錯而不會生成一個無效的值.這個行為在你使用過大或過小的數(shù)的時候提供了額外的安全性.

例如,Int16類型整數(shù)能容納的有符號整數(shù)范圍是-32768到32767,當(dāng)為一個Int16型變量賦的值超過這個范圍時,系統(tǒng)就會報錯:
<pre><code>var potentialOverflow = Int16.max //potentialOverflow的值是32767,這是Int16能容納的最大整數(shù) potentialOverflow += 1 //這里會報錯:Arithmetic operation '32767 + 1' (on type 'Int16') results in an overflow</code></pre>

當(dāng)值變得過大或者過小時提供錯誤處理能讓你在對邊界值進行編碼時更加靈活

然而,當(dāng)你想要在溢出時截取有效值,你可以采用溢出運算而不是錯誤處理.Swift提供了3個溢出運算符來支持整數(shù)計算的溢出行為.這些運算符都是以(&)開頭的:

  • 溢出加法(&+)
  • 溢出減法(&-)
  • 溢出乘法(&)*

數(shù)值溢出

數(shù)值可以在正反方向上溢出

如下演示了當(dāng)使用溢出加法(&+),允許一個無符號整數(shù)上溢時會發(fā)生什么:
<pre><code>var unsignedOverflow = UInt8.max //unsignedOverflow等于UInt8所能容納的最大整數(shù)255 unsignedOverflow = unsignedOverflow &+ 1 //此時unsignedOverflow等于0</code></pre>

unsignedOverflow變量被初始化為UInt8所能容納的最大整數(shù)(255,以二進制表示即11111111).然后使用了溢出加法運算符(&+)對其進行加1運算.這使得它的二進制表示正好超出UInt8所能容納的位數(shù),也就導(dǎo)致了數(shù)值的溢出,如下圖所示.數(shù)值溢出后,留在UInt8邊界內(nèi)的值是00000000,也就是十進制的0

overflowAddition.png

當(dāng)我們允許一個無符號整數(shù)下溢時也會產(chǎn)生類似的現(xiàn)象.這是一個使用溢出減法(&-)的示例:
<pre><code>var unsignedOverflow = UInt8.min // unsignedOverflow等于UInt8所能容納的最小整數(shù)0 unsignedOverflow = unsignedOverflow &- 1 // 此時 unsignedOverflow 等于 255</code></pre>

UInt8型整數(shù)能容納的最小值是0,以二進制表示即00000000.當(dāng)使用溢出減法運算符對其進行減1運算時,數(shù)值會產(chǎn)生下溢并被截斷為11111111,也就是十進制的255

overflowUnsignedSubtraction.png

溢出也會發(fā)生在有符號整型數(shù)值上.在對有符號整型數(shù)值進行溢出加法或溢出減法運算時,符號位也需要參與計算,如同按位左移/右移運算符所描述的那樣
<pre><code>var signedOverflow = Int8.min //signedOverflow等于Int8所能容納的最小整數(shù)-128 signedOverflow = signedOverflow &- 1 //此時signedOverflow等于127</code></pre>

Int8類型整數(shù)能容納的最小值是-128,以二進制表示即10000000.當(dāng)使用溢出減法運算符對其進行減1運算時,符號位被翻轉(zhuǎn),得到二進制數(shù)值01111111,也就是十進制數(shù)值的127,這個值也是Int8型整數(shù)所能容納的最大值.


overflowSignedSubtraction.png

對于無符號與有符號整型數(shù)值來說,在正方向溢出時會從所能容納的最大值變成最小值,在負方向溢出時會從所能容納的最小值變成最大值

優(yōu)先級和結(jié)合性(Precedence and Associativity)

運算符的優(yōu)先級 使一些運算符的級別高于其他運算符;高優(yōu)先級的運算符會先被使用.

運算符的結(jié)合性 定義了相同優(yōu)先級的運算符是如何結(jié)合的,是與左邊結(jié)合為一組,還是與右邊結(jié)合為一組.可理解為“它們是與左邊的表達式結(jié)合的”,或者“它們是與右邊的表達式結(jié)合的”.

在復(fù)合表達式的運算順序中,考慮運算符的優(yōu)先級和結(jié)合性是非常重要的.例如,運算符優(yōu)先級解釋了為什么下面這個表達式的結(jié)果會是17
<pre><code>2 + 3 % 4 * 5 // 結(jié)果是 17</code></pre>

如果你死板的從左到右進行閱讀,表達式的運算會是這樣的:

2 + 3 = 5
5 % 4 = 1
1 * 5 = 5

但是正確答案是17而不是5

優(yōu)先級高的運算符要先于優(yōu)先級低的運算符進行計算.
與C語言類似,在Swift中,取余運算符(%)與乘法運算符(*)的優(yōu)先級高于加法運算符(+).因此,它們的計算順序要先于加法運算符

而乘法與取余的優(yōu)先級相同.這時為了得到正確的運算順序,還需要考慮結(jié)合性.取余運算與乘法都是左結(jié)合的.可以將這考慮成為表達式的這些部分都隱式地加上了括號:

2 + ((3 % 4) * 5)

(3 % 4)等于3,所以表達式相當(dāng)于:

2 + (3 * 5)

3 * 5等于15,所以表達式相當(dāng)于:

2 + 15

因此計算結(jié)果為17

想要完整的Swift運算符優(yōu)先級和結(jié)合性規(guī)則,請參考Expressions.
Swift標(biāo)準庫提供所有的運算符的信息,請查看Swift Standard Library Operators Reference

注意
Swift的運算符優(yōu)先級和結(jié)合性規(guī)則比C語言和Objective-C中的更加簡單和可預(yù)測.但是,這意味著它們在基于C的語言中并不是完全一致的.在把現(xiàn)有的代碼移植到Swift的時候,要注意確保運算符的行為仍然符合你的想法

運算符函數(shù)(Operator Functions)

類和結(jié)構(gòu)體可以為現(xiàn)有的運算符提供自定義的實現(xiàn),被稱為運算符重載

下例中展示了如何為自定義的結(jié)構(gòu)體實現(xiàn)加法運算符(+).算術(shù)加法運算符是一個雙目運算符,因為它對兩個值進行運算,同時它還是中綴運算符,因為它出現(xiàn)在兩個值中間.

下例中定義了一個名為Vector2D的結(jié)構(gòu)體用來表示二維坐標(biāo)向量(x, y),緊接著定義了一個可以對兩個Vector2D結(jié)構(gòu)體進行相加的運算符函數(shù):
<pre><code>struct Vector2D { var x = 0.0, y = 0.0 } func + (left: Vector2D, right: Vector2D) -> Vector2D { return Vector2D(x: left.x + right.x, y: left.y + right.y) }</code></pre>

該運算符函數(shù)被定義為一個全局函數(shù),并且函數(shù)的名字與它要進行重載的+名字一致.因為算術(shù)加法運算符是雙目運算符,所以這個運算符函數(shù)接收兩個類型為Vector2D的參數(shù),同時有一個Vector2D類型的返回值.

在這個實現(xiàn)中,輸入?yún)?shù)分別被命名為left和right,代表在+運算符左邊和右邊的兩個Vector2D實例.函數(shù)返回了一個新的Vector2D實例,這個實例的x和y分別等于作為參數(shù)的兩個實例的x和y的值之和.

這個函數(shù)被定義成全局的,而不是Vector2D結(jié)構(gòu)體的成員方法,所以任意兩個Vector2D實例都可以使用這個中綴運算符:
<pre><code>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) print(combinedVector.x,combinedVector.y) //5.0 5.0</code></pre>

這個例子實現(xiàn)兩個向量(3.0,1.0)和(2.0,4.0)的相加,并得到新的向量(5.0,5.0).這個過程如下圖示:

vectorAddition.png

前綴和后綴運算符(Prefix and Postifx Operators)

上個例子顯示了一個雙目中綴運算符的自定義實現(xiàn).
類與結(jié)構(gòu)體也能提供標(biāo)準單目運算符的實現(xiàn).
單目運算符只操作一個值.當(dāng)運算符出現(xiàn)在值之前它就是前綴的(例如-a),而當(dāng)它出現(xiàn)在值之后它就是后綴的(例如b!)

當(dāng)聲明運算符函數(shù)的時,你通過在func關(guān)鍵字之前指定prefix或者postfix修飾符來實現(xiàn)一個單目前綴運算符
<pre><code>prefix func - (vector: Vector2D) -> Vector2D { return Vector2D(x: -vector.x, y: -vector.y) }</code></pre>

這段代碼為Vector2D類型實現(xiàn)了單目負號運算符.
由于該運算符是前綴運算符,所以這個函數(shù)需要加上prefix修飾符.

對于簡單數(shù)值,單目負號運算符可以對它們的正負性進行改變,對于Vector2D來說,該運算將其x和y屬性的正負性都進行了改變:
<pre><code>let positive = Vector2D(x: 3.0, y: 4.0) let negative = -positive //negative是一個值為(-3.0, -4.0)的Vector2D實例 let alsoPositive = -negative //alsoPositive是一個值為(3.0, 4.0)的Vector2D實例</code></pre>

復(fù)合賦值運算符

復(fù)合賦值運算符將賦值運算符(=)與其它運算符進行結(jié)合.
例如,將加法與賦值結(jié)合成加法賦值運算符(+=).
在實現(xiàn)的時候,需要把運算符的左參數(shù)設(shè)置成inout類型,因為這個參數(shù)的值會在運算符函數(shù)內(nèi)直接被修改.
<pre><code>func += (inout left: Vector2D, right: Vector2D) { left = left + right }</code></pre>

因為加法運算在之前已經(jīng)定義過了,所以在這里無需重新定義.加法賦值運算符函數(shù)可以直接利用現(xiàn)有的加法運算符函數(shù),用它來對左值和右值進行相加,并再次賦值給左值:
<pre><code>var original = Vector2D(x: 1.0, y: 2.0) let vectorToAdd = Vector2D(x: 3.0, y: 4.0) original += vectorToAdd //original的值現(xiàn)在為(4.0, 6.0) print(original.x,original.y) //4.0 6.0</code></pre>

注意
不能對默認的賦值運算符(=)進行重載
只有組合賦值運算符可以被重載
同樣地,也無法對三目條件運算符(a ? b : c)進行重載

等價運算符(Equivalence Operators)

自定義的類和結(jié)構(gòu)體沒有獲得對等價運算符進行默認實現(xiàn),等價運算符通常被稱為“相等”運算符(==)與“不等”運算符(!=).
對于自定義類型,Swift 無法判斷其是否“相等”,因為“相等”的含義取決于這些自定義類型在你的代碼中所扮演的角色.

為了使用等價運算符能對自定義的類型的等價進行檢查,為其提供如同為其它中綴運算符那樣的自定義實現(xiàn):
<pre><code>func == (left: Vector2D, right: Vector2D) -> Bool { return (left.x == right.x) && (left.y == right.y) } func != (left: Vector2D, right: Vector2D) -> Bool { return !(left == right) }</code></pre>

上述代碼實現(xiàn)了“相等”運算符(==)來判斷兩個Vector2D實例是否相等.對Vector2D類型來說,“相等”意味著“兩個實例的x屬性和y屬性都相等”,并且這也是“相等”運算符的實現(xiàn)所采用的邏輯.示例同時也實現(xiàn)了“不等”運算符(!=).它簡單地將“相等”運算符的結(jié)果進行取反后返回.

現(xiàn)在我們可以使用這兩個運算符來判斷兩個Vector2D實例是否相等:
<pre><code>`
var vector0 = Vector2D(x: 1.0, y: 2.0)
var vector1 = Vector2D(x: 1.0, y: 2.0)

if vector0 == vector1
{
print("These two vectors are equivalent.")
}
else
{
print("These two vectors are not equivalent.")
}

vector1 = Vector2D(x: 2.0, y: 3.0)

if vector0 == vector1
{
print("These two vectors are equivalent.")
}
else
{
print("These two vectors are not equivalent.")
}
//These two vectors are equivalent.
//These two vectors are not equivalent.
`</code></pre>

自定義運算符

除了Swift提供的標(biāo)準運算符,你可以聲明和實現(xiàn)自定義運算符.
可以用來自定義運算符的字符的列表請參考Operators.

新的運算符要使用operator關(guān)鍵字在全局作用域內(nèi)進行定義,
同時還要用prefix,infix或者postfix修飾符標(biāo)記:
<pre><code>prefix operator +++ {}</code></pre>

上面的實例中定義了一個新的名為+++的前綴運算符.這個運算符在Swift中沒有意義,因此我們對于Vector2D的實例來自定義它的意義.對這個示例,+++被視為“前綴翻倍”運算符.它使用了前面定義的復(fù)合加法運算符對自身進行相加,從而讓Vector2D實例的x屬性和y屬性的值翻倍:
<pre><code>prefix func +++ (inout vector: Vector2D) -> Vector2D { vector += vector return vector } var toBeDoubled = Vector2D(x: 1.0, y: 4.0) let afterDoubling = +++toBeDoubled //toBeDoubled現(xiàn)在的值為(2.0, 8.0) //afterDoubling現(xiàn)在的值也為(2.0, 8.0) print(toBeDoubled) print(afterDoubling) //Vector2D(x: 2.0, y: 8.0) //Vector2D(x: 2.0, y: 8.0)</code></pre>

自定義中綴運算符的優(yōu)先級和結(jié)合性

自定義的中綴運算符也可以指定優(yōu)先級和結(jié)合性.Precedence and Associativity中詳細解釋了這兩個特性是如何影響自定義的中綴運算符與其他中綴運算符的關(guān)系.

結(jié)合性的可取值有l(wèi)eft,right和none.當(dāng)左結(jié)合運算符跟其他相同優(yōu)先級的左結(jié)合運算符寫在一起時,會跟左邊的值進行結(jié)合.同理,當(dāng)右結(jié)合運算符跟其他相同優(yōu)先級的右結(jié)合運算符寫在一起時,會跟右邊的值進行結(jié)合.而非結(jié)合運算符不能跟其他相同優(yōu)先級的運算符寫在一起.

結(jié)合性的默認值是none,優(yōu)先級的值是100.

以下例子定義了一個新的中綴運算符+-,此運算符的結(jié)合性為left,并且它的優(yōu)先級為140:
<pre><code>infix operator +- { associativity left precedence 140 } func +- (left: Vector2D, right: Vector2D) -> Vector2D { return Vector2D(x: left.x + right.x, y: left.y - right.y) } let firstVector = Vector2D(x: 1.0, y: 2.0) let secondVector = Vector2D(x: 3.0, y: 4.0) let plusMinusVector = firstVector +- secondVector //plusMinusVector是一個Vector2D實例,并且它的值為(4.0, -2.0)</code></pre>

這個運算符把兩個向量的x值相加,同時用第一個向量的y值減去第二個向量的y值.因為它本質(zhì)上是屬于“相加型”運算符,所以將它的結(jié)合性和優(yōu)先級被分別設(shè)置為left和140,這與+和-等默認的中綴“相加型”運算符是相同的.關(guān)于Swift標(biāo)準庫提供的運算符的結(jié)合性與優(yōu)先級,參考Swift Standard Library Operators Reference

注意
當(dāng)定義前綴與后綴運算符的時候,你不需要指定優(yōu)先級.
如果對同一個被操作數(shù)同時使用前綴與后綴運算符,則后綴運算符會先參與運算.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末擒滑,一起剝皮案震驚了整個濱河市析显,隨后出現(xiàn)的幾起案子仁烹,更是在濱河造成了極大的恐慌鹃彻,老刑警劉巖茶没,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件侈询,死亡現(xiàn)場離奇詭異舌涨,居然都是意外死亡,警方通過查閱死者的電腦和手機扔字,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門泼菌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人啦租,你說我怎么就攤上這事哗伯。” “怎么了篷角?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵焊刹,是天一觀的道長。 經(jīng)常有香客問我恳蹲,道長虐块,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任嘉蕾,我火速辦了婚禮贺奠,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘错忱。我一直安慰自己儡率,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布以清。 她就那樣靜靜地躺著儿普,像睡著了一般。 火紅的嫁衣襯著肌膚如雪掷倔。 梳的紋絲不亂的頭發(fā)上眉孩,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天,我揣著相機與錄音勒葱,去河邊找鬼浪汪。 笑死,一個胖子當(dāng)著我的面吹牛凛虽,可吹牛的內(nèi)容都是我干的死遭。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼涩维,長吁一口氣:“原來是場噩夢啊……” “哼殃姓!你這毒婦竟也來了袁波?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤蜗侈,失蹤者是張志新(化名)和其女友劉穎篷牌,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體踏幻,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡枷颊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了该面。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片夭苗。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖隔缀,靈堂內(nèi)的尸體忽然破棺而出题造,到底是詐尸還是另有隱情,我是刑警寧澤猾瘸,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布界赔,位于F島的核電站,受9級特大地震影響牵触,放射性物質(zhì)發(fā)生泄漏淮悼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一揽思、第九天 我趴在偏房一處隱蔽的房頂上張望袜腥。 院中可真熱鬧,春花似錦钉汗、人聲如沸羹令。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽特恬。三九已至,卻和暖如春徐钠,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背役首。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工尝丐, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人衡奥。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓爹袁,卻偏偏與公主長得像,于是被迫代替她去往敵國和親矮固。 傳聞我的和親對象是個殘疾皇子失息,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 本章將會介紹 模塊和源文件訪問級別訪問控制語法自定義類型子類常量盹兢、變量邻梆、屬性、下標(biāo)構(gòu)造器協(xié)議擴展泛型類型別名位運算...
    寒橋閱讀 874評論 0 2
  • 高級運算符 文檔地址 作為 基本運算符 的補充绎秒,Swift 提供了幾個高級運算符執(zhí)行對數(shù)傳值進行更加復(fù)雜的操作浦妄。這...
    hrscy閱讀 830評論 0 2
  • 關(guān)于 Swift 重要這個文檔所包含的準備信息, 是關(guān)于開發(fā)的 API 和技術(shù)的。這個信息可能會改變, 根據(jù)這個文...
    無灃閱讀 4,275評論 1 27
  • 這是一個悲傷的故事,這是一個失敗的故事玄呛,這是一個絕望的故事阅懦,這是真實的故事。 如果徘铝,假如生命有如果故黑,回到那個起點,...
    lovejasmine閱讀 220評論 0 1
  • 喜歡一個人久了,就會變成習(xí)慣怠缸。習(xí)慣到你都不知道自己到底喜不喜歡他诗轻,但是每當(dāng)別人問到你有喜歡的人嗎?你腦海里閃...
    阿SUN閱讀 286評論 0 0