> 1.0 翻譯:[xielingwang](https://github.com/xielingwang)?校對:[numbbbbb](https://github.com/numbbbbb)
>
> 2.0 翻譯+校對:[buginux](https://github.com/buginux)
本頁內容包括:
[TOC=2]
除了在之前介紹過的基本運算符,Swift 中還有許多可以對數值進行復雜操作的高級運算符。這些高級運算符包含了在 C 和 Objective-C 中已經被大家所熟知的位運算符和移位運算符。
與C語言中的算術運算符不同,Swift 中的算術運算符默認是不會溢出的。所有溢出行為都會被捕獲并報告為錯誤。如果想讓系統允許溢出行為,可以選擇使用 Swift 中另一套默認支持溢出的運算符,比如溢出加法運算符(`&+`)。所有的這些溢出運算符都是以?`&`?開頭的。
在定義自有的結構體、類和枚舉時,最好也同時為它們提供標準swift運算符的實現。Swift簡化了運算符的自定義實現,也使判斷不同類型所對應的行為更為簡單。
我們不用被預定義的運算符所限制。在 Swift 當中可以自由地定義中綴、前綴、后綴和賦值運算符,以及相應的優先級與結合性。這些運算符在代碼中可以像預設的運算符一樣使用,我們甚至可以擴展已有的類型以支持自定義的運算符。
## 位運算符
位運算符(`Bitwise operators`)可以操作一個數據結構中每個獨立的位。它們通常被用在底層開發中,比如圖形編程和創建設備驅動。位運算符在處理外部資源的原始數據時也十分有用,比如對自定義通信協議傳輸的數據進行編碼和解碼。
Swift 支持C語言中的全部位運算符,具體如下:
### 按位取反運算符(`bitwise NOT operator`)
按位取反運算符(`~`) 可以對一個數值的全部位進行取反:

按位取反操作符是一個前置運算符,需要直接放在操作數的之前,并且它們之間不能添加任何空格。
~~~
let initialBits: UInt8 = 0b00001111
let invertedBits = ~initialBits // 等于 0b11110000
~~~
`UInt8`?類型的整數有 8 個比特位,可以存儲 0 ~ 255之間的任意整數。這個例子初始化了一個?`UInt8`?類型的整數,并賦值為二進制的?`00001111`,它的前 4 位都為`0`,后 4 位都為`1`。這個值等價于十進制的?`15`?。
接著使用按位取反運算符創建了一個名為?`invertedBits`?的常量,這個常量的值與全部位取反后的?`initialBits`?相等。即所有的?`0`?都變成了?`1`,同時所有的?`1`?都變成?`0`。`invertedBits`?的二進制值為?`11110000`,等價于無符號十進制數的?`240`。
### 按位與運算符(Bitwise AND Operator)
按位與運算符(`&`)可以對兩個數的比特位進行合并。它返回一個新的數,只有當兩個操作數的對應位_都_為?`1`?的時候,該數的對應位才為?`1`。

在下面的示例當中,`firstSixBits`?和?`lastSixBits`?中間 4 個位的值都為 1 。按位與運算符對它們進行了運算,得到二進制數值?`00111100`,等價于無符號十進制數的?`60`:
~~~
let firstSixBits: UInt8 = 0b11111100
let lastSixBits: UInt8 = 0b00111111
let middleFourBits = firstSixBits & lastSixBits // 等于 00111100
~~~
### 按位或運算符(Bitwise OR Operator)
按位或運算符(`|`)可以對兩個數的比特位進行比較。它返回一個新的數,只要兩個操作數的對應位中有_任意_一個為?`1`時,該數的對應位就為?`1`。

在下面的示例當中,`someBits`?和?`moreBits`?將不同的位設置為?`1`。接位或運算符對它們進行了運算,得到二進制數值`11111110`,等價于無符號十進制數的?`254`:
~~~
let someBits: UInt8 = 0b10110010
let moreBits: UInt8 = 0b01011110
let combinedbits = someBits | moreBits // 等于 11111110
~~~
### 按位異或運算符(Bitwise XOR Opoerator)
按位異或運算符(`^`)可以對兩個數的比特位進行比較。它返回一個新的數,當兩個操作數的對應位不相同時,該數的對應位就為?`1`:

在下面的示例當中,`firstBits`?和?`otherBits`?都有一個自己設置為?`1`?而對方設置為?`0`?的位。 按位異或運算符將這兩個位都設置為?`1`,同時將其它位都設置為?`0`:
~~~
let firstBits: UInt8 = 0b00010100
let otherBits: UInt8 = 0b00000101
let outputBits = firstBits ^ otherBits // 等于 00010001
~~~
### 按位左移/右移運算符
按位左移運算符(`<<`)和按位右移運算符(`>>`)可以對一個數進行指定位數的左移和右移,但是需要遵守下面定義的規則。
對一個數進行按位左移或按位右移,相當于對這個數進行乘以 2 或除以 2 的運算。將一個整數左移一位,等價于將這個數乘以 2,同樣地,將一個整數右移一位,等價于將這個數除以 2。
#### 無符號整型的移位操作
對無符號整型進行移位的規則如下:
1. 已經存在的比特位按指定的位數進行左移和右移。
2. 任何移動超出整型存儲邊界的位都會被丟棄。
3. 用 0 來填充移動后產生的空白位。
這種方法稱為邏輯移位(`logical shift`)。
以下這張圖展示了?`11111111 << 1`(即把?`11111111`?向左移動 1 位),和?`11111111 >> 1`(即把?`11111111`?向右移動 1 位) 的結果。藍色的部分是被移位的,灰色的部分是被拋棄的,橙色的部分則是被填充進來的。

下面的代碼演示了 Swift 中的移位操作:
~~~
let shiftBits: UInt8 = 4 // 即二進制的00000100
shiftBits << 1 // 00001000
shiftBits << 2 // 00010000
shiftBits << 5 // 10000000
shiftBits << 6 // 00000000
shiftBits >> 2 // 00000001
~~~
可以使用移位操作對其他的數據類型進行編碼和解碼:
~~~
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
~~~
這個示例使用了一個命名為?`pink`?的?`UInt32`?型常量來存儲層疊樣式表(`CSS`)中粉色的顏色值。該?`CSS`?的十六進制顏色值?`#CC6699`, 在 Swift 中表示為?`0xCC6699`。然后利用按位與運算符(`&`)和按位右移運算符(`>>`)從這個顏色值中分解出紅(`CC`)、綠(`66`)以及藍(`99`)三個部分。
紅色部分是通過對?`0xCC6699`?和?`0xFF0000`?進行按位與運算后得到的。`0xFF0000`?中的?`0`?部分作為_掩碼_,掩蓋了`OxCC6699`?中的第二和第三個字節,使得數值中的?`6699`?被忽略,只留下?`0xCC0000`。
然后,再將這個數按向右移動 16 位(`>> 16`)。十六進制中每兩個字符表示 8 個比特位,所以移動 16 位后?`0xCC0000`?就變為?`0x0000CC`。這個數和`0xCC`是等同的,也就是十進制數值的?`204`。
同樣的,綠色部分通過對?`0xCC6699`?和?`0x00FF00`?進行按位與運算得到?`0x006600`。然后將這個數向右移動 8 位,得到`0x66`,也就是十進制數值的?`102`。
最后,藍色部分通過對?`0xCC6699`?和?`0x0000FF`?進行按位與運算得到?`0x000099`。并且不需要進行向右移位,所以結果為`0x99`?,也就是十進制數值的?`153`。
#### 有符號整型的移位操作
對比無符號整型來說,有符整型的移位操作相對復雜得多,這種復雜性源于有符號整數的二進制表現形式。(為了簡單起見,以下的示例都是基于 8 位有符號整數的,但是其中的原理對任何位數的有符號整數都是通用的。)
有符號整數使用第 1 個比特位(通常被稱為符號位)來表示這個數的正負。符號位為?`0`?代表正數,為?`1`?代表負數。
其余的比特位(通常被稱為數值位)存儲了這個數的真實值。有符號正整數和無符號數的存儲方式是一樣的,都是從?`0`?開始算起。這是值為?`4`?的?`Int8`?型整數的二進制位表現形式:

符號位為?`0`,說明這是一個正數,另外 7 位則代表了十進制數值?`4`?的二進制表示。
負數的存儲方式略有不同。它存儲的是?`2`?的 n 次方減去它的真實值絕對值,這里的 n 為數值位的位數。一個 8 位的數有 7 個數值位,所以是 2 的 7 次方,即 128。
這是值為?`-4`?的?`Int8`?型整數的二進制位表現形式:

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

負數的表示通常被稱為二進制補碼(`two's complement`)表示法。用這種方法來表示負數乍看起來有點奇怪,但它有幾個優點。
首先,如果想對?`-1`?和?`-4`?進行加法操作,我們只需要將這兩個數的全部 8 個比特位進行相加,并且將計算結果中超出 8 位的數值丟棄:

其次,使用二進制補碼可以使負數的按位左移和右移操作得到跟正數同樣的效果,即每向左移一位就將自身的數值乘以 2,每向右一位就將自身的數值除以 2。要達到此目的,對有符號整數的右移有一個額外的規則:
* 當對正整數進行按位右移操作時,遵循與無符號整數相同的規則,但是對于移位產生的空白位使用_符號位_進行填充,而不是用 0。

這個行為可以確保有符號整數的符號位不會因為右移操作而改變,這通常被稱為算術移位(`arithmetic shift`)。
由于正數和負數的特殊存儲方式,在對它們進行右移的時候,會使它們越來越接近 0。在移位的過程中保持符號位不變,意味著負整數在接近?`0`?的過程中會一直保持為負。
## 溢出運算符
在默認情況下,當向一個整數賦超過它容量的值時,Swift 默認會報錯,而不是生成一個無效的數。這個行為給我們操作過大或著過小的數的時候提供了額外的安全性。
例如,`Int16`?型整數能容納的有符號整數范圍是?`-32768`?到?`32767`,當為一個?`Int16`?型變量賦的值超過這個范圍時,系統就會報錯:
~~~
var potentialOverflow = Int16.max
// potentialOverflow 的值是 32767, 這是 Int16 能容納的最大整數
potentialOverflow += 1
// 這里會報錯
~~~
為過大或者過小的數值提供錯誤處理,能讓我們在處理邊界值時更加靈活。
然而,也可以選擇讓系統在數值溢出的時候采取截斷操作,而非報錯。可以使用 Swift 提供的三個溢出操作符(`overflow operators`)來讓系統支持整數溢出運算。這些操作符都是以?`&`?開頭的:
* 溢出加法?`&+`
* 溢出減法?`&-`
* 溢出乘法?`&*`
### 數值溢出
數值有可能出現上溢或者下溢。
這個示例演示了當我們對一個無符號整數使用溢出加法(`&+`)進行上溢運算時會發生什么:
~~~
var unsignedOverflow = UInt8.max
// unsignedOverflow 等于 UInt8 所能容納的最大整數 255
unsignedOverflow = unsignedOverflow &+ 1
// 此時 unsignedOverflow 等于 0
~~~
`unsignedOverflow`?被初始化為?`UInt8`?所能容納的最大整數(`255`,以二進制表示即?`11111111`)。然后使用了溢出加法運算符(`&+`)對其進行加 1 操作。這使得它的二進制表示正好超出?`UInt8`?所能容納的位數,也就導致了數值的溢出,如下圖所示。數值溢出后,留在?`UInt8`?邊界內的值是?`00000000`,也就是十進制數值的 0。

同樣地,當我們對一個無符號整數使用溢出減法(`&-`)進行下溢運算時也會產生類似的現象:
~~~
var unsignedOverflow = UInt8.min
// unsignedOverflow 等于 UInt8 所能容納的最小整數 0
unsignedOverflow = unsignedOverflow &- 1
// 此時 unsignedOverflow 等于 255
~~~
`UInt8`?型整數能容納的最小值是 0,以二進制表示即?`00000000`。當使用溢出減法運算符對其進行減 1 操作時,數值會產生下溢并被截斷為?`11111111`, 也就是十進制數值的 255。

溢出也會發生在有符號整型數值上。在對有符號整型數值進行溢出加法或溢出減法運算時,符號位也需要參與計算,正如[按位左移/右移運算符](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AdvancedOperators.html#//apple_ref/doc/uid/TP40014097-CH27-ID34)所描述的。
~~~
var signedOverflow = Int8.min
// signedOverflow 等于 Int8 所能容納的最小整數 -128
signedOverflow = signedOverflow &- 1
// 此時 signedOverflow 等于 127
~~~
`Int8`?型整數能容納的最小值是 -128,以二進制表示即?`10000000`。當使用溢出減法操作符對其進行減 1 操作時,符號位被翻轉,得到二進制數值?`01111111`,也就是十進制數值的?`127`,這個值也是?`Int8`?型整數所能容納的最大值。

對于無符號與有符號整型數值來說,當出現上溢時,它們會從數值所能容納的最大數變成最小的數。同樣地,當發生下溢時,它們會從所能容納的最小數變成最大的數。
## 優先級和結合性
運算符的優先級(`precedence`)使得一些運算符優先于其他運算符,高優先級的運算符會先被計算。
結合性(`associativity`)定義了相同優先級的運算符是如何結合(或關聯)的 —— 是與左邊結合為一組,還是與右邊結合為一組。可以將這意思理解為“它們是與左邊的表達式結合的”或者“它們是與右邊的表達式結合的”。
在復合表達式的運算順序中,運算符的優先級和結合性是非常重要的。舉例來說,為什么下面這個表達式的運算結果是`4`?
~~~
2 + 3 * 4 % 5
// 結果是 4
~~~
如果嚴格地從左到右進行運算,則運算的過程是這樣的:
* 2 + 3 = 5
* 5 * 4 = 20
* 20 % 5 = 0
但是正確答案是?`4`?而不是?`0`。優先級高的運算符要先于優先級低的運算符進行計算。與C語言類似,在 Swift 當中,乘法運算符(`*`)與取余運算符(`%`)的優先級高于加法運算符(`+`)。因此,它們的計算順序要先于加法運算。
而乘法與取余的優先級相同。這時為了得到正確的運算順序,還需要考慮結合性。乘法與取余運算都是左結合的。可以將這考慮成為這兩部分表達式都隱式地加上了括號:
~~~
2 + ((3 * 4) % 5)
~~~
`(3 * 4) = 12`,所以表達式相當于:
~~~
2 + (12 % 5)
~~~
`12 % 5 = 2`,所以表達式相當于:
~~~
2 + 2
~~~
此時可以容易地看出計算的結果為?`4`。
如果想查看完整的 Swift 運算符優先級和結合性規則,請參考[表達式](http://wiki.jikexueyuan.com/project/swift/chapter3/04_Expressions.html)。
> 注意:
> 對于C語言和 Objective-C 來說,Swift 的運算符優先級和結合性規則是更加簡潔和可預測的。但是,這也意味著它們于那些基于C的語言不是完全一致的。在對現有的代碼進行移植的時候,要注意確保運算符的行為仍然是按照你所想的那樣去執行。
## 運算符函數
類和結構可以為現有的操作符提供自定義的實現,這通常被稱為運算符重載(`overloading`)。
下面的例子展示了如何為自定義的結構實現加法操作符(`+`)。算術加法運算符是一個兩目運算符(`binary operator`),因為它可以對兩個目標進行操作,同時它還是中綴(`infix`)運算符,因為它出現在兩個目標中間。
例子中定義了一個名為?`Vector2D`?的結構體用來表示二維坐標向量`(x, y)`,緊接著定義了一個可以對兩個?`Vector2D`?結構體進行相加的運算符函數(`operator function`):
~~~
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)
}
~~~
該運算符函數被定義為一個全局函數,并且函數的名字與它要進行重載的?`+`?名字一致。因為算術加法運算符是雙目運算符,所以這個運算符函數接收兩個類型為?`Vector2D`?的輸入參數,同時有一個?`Vector2D`?類型的返回值。
在這個實現中,輸入參數分別被命名為?`left`?和?`right`,代表在?`+`?運算符左邊和右邊的兩個?`Vector2D`?對象。函數返回了一個新的?`Vector2D`?的對象,這個對象的?`x`?和?`y`?分別等于兩個參數對象的?`x`?和?`y`?的值之和。
這個函數被定義成全局的,而不是?`Vector2D`?結構的成員方法,所以任意兩個?`Vector2D`?對象都可以使用這個中綴運算符:
~~~
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)
~~~
這個例子實現兩個向量?`(3.0,1.0)`?和?`(2.0,4.0)`?的相加,并得到新的向量?`(5.0,5.0)`。這個過程如下圖示:

### 前綴和后綴運算符
上個例子演示了一個雙目中綴運算符的自定義實現。類與結構體也能提供標準單目運算符(`unary operators`)的實現。單目運算符只有一個操作目標。當運算符出現在操作目標之前時,它就是前綴(`prefix`)的(比如?`-a`),而當它出現在操作目標之后時,它就是后綴(`postfix`)的(比如?`i++`)。
要實現前綴或者后綴運算符,需要在聲明運算符函數的時候在?`func`?關鍵字之前指定?`prefix`?或者?`postfix`?限定符:
~~~
prefix func - (vector: Vector2D) -> Vector2D {
return Vector2D(x: -vector.x, y: -vector.y)
}
~~~
這段代碼為?`Vector2D`?類型實現了單目減運算符(`-a`)。由于單目減運算符是前綴運算符,所以這個函數需要加上`prefix`?限定符。
對于簡單數值,單目減運算符可以對它們的正負性進行改變。對于?`Vector2D`?來說,單目減運算將其?`x`?和?`y`?屬性的正負性都進行了改變。
~~~
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 實例
~~~
### 復合賦值運算符
復合賦值運算符(`Compound assignment operators`)將賦值運算符(`=`)與其它運算符進行結合。比如,將加法與賦值結合成加法賦值運算符(`+=`)。在實現的時候,需要把運算符的左參數設置成?`inout`?類型,因為這個參數的值會在運算符函數內直接被修改。
~~~
func += (inout left: Vector2D, right: Vector2D) {
left = left + right
}
~~~
因為加法運算在之前已經定義過了,所以在這里無需重新定義。在這里可以直接利用現有的加法運算符函數,用它來對左值和右值進行相加,并再次賦值給左值:
~~~
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)
~~~
還可以將賦值與?`prefix`?或?`postfix`?限定符結合起來,下面的代碼為?`Vector2D`?實例實現了前綴自增運算符(`++a`):
~~~
prefix func ++ (inout vector: Vector2D) -> Vector2D {
vector += Vector2D(x: 1.0, y: 1.0)
return vector
}
~~~
這個前綴自增運算符使用了前面定義的加法賦值操作。它對?`Vector2D`?的?`x`?和?`y`?屬性都進行了加?`1`?操作,再將結果返回:
~~~
var toIncrement = Vector2D(x: 3.0, y: 4.0)
let afterIncrement = ++toIncrement
// toIncrement 的值現在為 (4.0, 5.0)
// afterIncrement 的值同樣為 (4.0, 5.0)
~~~
> 注意: 不能對默認的賦值運算符(`=`)進行重載。只有組合賦值符可以被重載。同樣地,也無法對三目條件運算符`a ? b : c`?進行重載。
### 等價操作符
自定義的類和結構體沒有對等價操作符(`equivalence operators`)進行默認實現,等價操作符通常被稱為“相等”操作符(`==`)與“不等”操作符(`!=`)。對于自定義類型,Swift 無法判斷其是否“相等”,因為“相等”的含義取決于這些自定義類型在你的代碼中所扮演的角色。
為了使用等價操作符來對自定義的類型進行判等操作,需要為其提供自定義實現,實現的方法與其它中綴運算符一樣:
~~~
func == (left: Vector2D, right: Vector2D) -> Bool {
return (left.x == right.x) && (left.y == right.y)
}
func != (left: Vector2D, right: Vector2D) -> Bool {
return !(left == right)
}
~~~
上述代碼實現了“相等”運算符(`==`)來判斷兩個?`Vector2D`?對象是否有相等。對于?`Vector2D`?類型來說,“相等”意味“兩個實例的?`x`屬性 和?`y`?屬性都相等”,這也是代碼中用來進行判等的邏輯。示例里同時也實現了“不等”操作符(`!=`),它簡單地將“相等”操作符進行取反后返回。
現在我們可以使用這兩個運算符來判斷兩個?`Vector2D`?對象是否相等。
~~~
let twoThree = Vector2D(x: 2.0, y: 3.0)
let anotherTwoThree = Vector2D(x: 2.0, y: 3.0)
if twoThree == anotherTwoThree {
print("These two vectors are equivalent.")
}
// prints "These two vectors are equivalent."
~~~
### 自定義運算符
除了實現標準運算符,在 Swift 當中還可以聲明和實現自定義運算符(`custom operators`)。可以用來自定義運算符的字符列表請參考[操作符](http://wiki.jikexueyuan.com/project/swift/chapter3/02_Lexical_Structure.html#operators)
新的運算符要在全局作用域內,使用?`operator`?關鍵字進行聲明,同時還要指定?`prefix`、`infix`?或者?`postfix`?限定符:
~~~
operator prefix +++ {}
~~~
上面的代碼定義了一個新的名為?`+++`?的前綴運算符。對于這個運算符,在 Swift 中并沒有意義,因為我們針對`Vector2D`?的實例來定義它的意義。對這個示例來講,`+++`?被實現為“前綴雙自增”運算符。它使用了前面定義的復合加法操作符來讓矩陣對自身進行相加,從而讓?`Vector2D`?實例的?`x`?屬性和?`y`屬性的值翻倍:
~~~
prefix func +++ (inout vector: Vector2D) -> Vector2D {
vector += vector
return vector
}
~~~
`Vector2D`?的?`+++`?的實現和?`++`?的實現很相似, 唯一不同的是前者對自身進行相加, 而后者是與另一個值為?`(1.0, 1.0)`的向量相加.
~~~
var toBeDoubled = Vector2D(x: 1.0, y: 4.0)
let afterDoubling = +++toBeDoubled
// toBeDoubled 現在的值為 (2.0, 8.0)
// afterDoubling 現在的值也為 (2.0, 8.0)
~~~
### 自定義中綴運算符的優先級和結合性
自定義的中綴(`infix`)運算符也可以指定優先級(`precedence`)和結合性(`associativity`)。[優先級和結合性](http://wiki.jikexueyuan.com/project/swift/chapter2/25_Advanced_Operators.html#PrecedenceandAssociativity)中詳細闡述了這兩個特性是如何對中綴運算符的運算產生影響的。
結合性(`associativity`)可取的值有`left`,`right`?和?`none`。當左結合運算符跟其他相同優先級的左結合運算符寫在一起時,會跟左邊的操作數進行結合。同理,當右結合運算符跟其他相同優先級的右結合運算符寫在一起時,會跟右邊的操作數進行結合。而非結合運算符不能跟其他相同優先級的運算符寫在一起。
結合性(`associativity`)的默認值是?`none`,優先級(`precedence`)如果沒有指定,則默認為?`100`。
以下例子定義了一個新的中綴運算符?`+-`,此操作符是左結合的,并且它的優先級為?`140`:
~~~
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)
~~~
這個運算符把兩個向量的?`x`?值相加,同時用第一個向量的?`y`?值減去第二個向量的?`y`?值。因為它本質上是屬于“加型”運算符,所以將它的結合性和優先級被設置為(`left`?和?`140`),這與?`+`?和?`-`?等默認的中綴加型操作符是相同的。完整的 Swift 操作符默認結合性與優先級請參考表達式。
> 注意: 當定義前綴與后綴操作符的時候,我們并沒有指定優先級。然而,如果對同一個操作數同時使用前綴與后綴操作符,則后綴操作符會先被執行。
- 介紹
- 歡迎使用 Swift
- 關于 Swift
- Swift 初見
- Swift 版本歷史記錄
- Swift1.0 發布內容
- Swift 教程
- 基礎部分
- 基本運算符
- 字符串和字符
- 集合類型
- 控制流
- 函數
- 閉包
- 枚舉
- 類和結構體
- 屬性
- 方法
- 下標腳本
- 繼承
- 構造過程
- 析構過程
- 自動引用計數
- 可選鏈
- 錯誤處理
- 類型轉換
- 嵌套類型
- 擴展
- 協議
- 泛型
- 權限控制
- 高級操作符
- 語言參考
- 關于語言參考
- 詞法結構
- 類型
- 表達式
- 語句
- 聲明
- 特性
- 模式
- 泛型參數
- 語法總結
- 蘋果官方Blog官方翻譯
- Access Control 權限控制的黑與白
- 造個類型不是夢-白話Swift類型創建
- WWDC里面的那個“大炮打氣球”
- Swift與C語言指針友好合作
- 引用類型和值類型的恩怨
- 訪問控制和Protected
- 可選類型完美解決占位問題