25,advanced opertors, for 3.0.1

This commit is contained in:
shanks
2016-11-13 20:19:35 +08:00
parent e130059ba0
commit 0b2daf4c77

View File

@ -1,4 +1,4 @@
# 高级运算符Advanced Operators
# 高级运算符
-----------------
> 1.0
@ -16,6 +16,7 @@
>
> 3.0
> 翻译+校对:[mmoaay](https://github.com/mmoaay) 2016-09-20
> 3.0.1shanks2016-11-13
本页内容包括:
@ -36,14 +37,14 @@
<a name="bitwise_operators"></a>
## 位运算符
位运算符可以操作数据结构中每个独立的比特位。它们通常被用在底层开发中,比如图形编程和创建设备驱动。位运算符在处理外部资源的原始数据时也十分有用,比如对自定义通信协议传输的数据进行编码和解码。
*位运算符*可以操作数据结构中每个独立的比特位。它们通常被用在底层开发中,比如图形编程和创建设备驱动。位运算符在处理外部资源的原始数据时也十分有用,比如对自定义通信协议传输的数据进行编码和解码。
Swift 支持 C 语言中的全部位运算符,接下来会一一介绍。
<a name="bitwise_not_operator"></a>
### 按位取反运算符
按位取反运算符(`~`)可以对一个数值的全部比特位进行取反:
*按位取反运算符(`~`*可以对一个数值的全部比特位进行取反:
![Art/bitwiseNOT_2x.png](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/bitwiseNOT_2x.png)
@ -62,7 +63,7 @@ let invertedBits = ~initialBits // 等于 0b11110000
<a name="bitwise_and_operator"></a>
### 按位与运算符
按位与运算符(`&`)可以对两个数的比特位进行合并。它返回一个新的数,只有当两个数的对应位都为 `1` 的时候,新数的对应位才为 `1`
*按位与运算符(`&`*可以对两个数的比特位进行合并。它返回一个新的数,只有当两个数的对应位都为 `1` 的时候,新数的对应位才为 `1`
![Art/bitwiseAND_2x.png](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/bitwiseAND_2x.png)
@ -77,7 +78,7 @@ let middleFourBits = firstSixBits & lastSixBits // 等于 00111100
<a name="bitwise_or_operator"></a>
### 按位或运算符
按位或运算符(`|`)可以对两个数的比特位进行比较。它返回一个新的数,只要两个数的对应位中有任意一个为 `1` 时,新数的对应位就为 `1`
*按位或运算符(`|`*可以对两个数的比特位进行比较。它返回一个新的数,只要两个数的对应位中有任意一个为 `1` 时,新数的对应位就为 `1`
![Art/bitwiseOR_2x.png](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/bitwiseOR_2x.png "Art/bitwiseOR_2x.png")
@ -92,7 +93,7 @@ let combinedbits = someBits | moreBits // 等于 11111110
<a name="bitwise_xor_operator"></a>
### 按位异或运算符
按位异或运算符(`^`)可以对两个数的比特位进行比较。它返回一个新的数,当两个数的对应位不相同时,新数的对应位就为 `1`
*按位异或运算符(`^`*可以对两个数的比特位进行比较。它返回一个新的数,当两个数的对应位不相同时,新数的对应位就为 `1`
![Art/bitwiseXOR_2x.png](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/bitwiseXOR_2x.png "Art/bitwiseXOR_2x.png")
@ -107,7 +108,7 @@ let outputBits = firstBits ^ otherBits // 等于 00010001
<a name="bitwise_left_and_right_shift_operators"></a>
### 按位左移、右移运算符
按位左移运算符(`<<`按位右移运算符(`>>`)可以对一个数的所有位进行指定位数的左移和右移,但是需要遵守下面定义的规则。
*按位左移运算符(`<<`*和*按位右移运算符(`>>`*可以对一个数的所有位进行指定位数的左移和右移,但是需要遵守下面定义的规则。
对一个数进行按位左移或按位右移,相当于对这个数进行乘以 2 或除以 2 的运算。将一个整数左移一位,等价于将这个数乘以 2同样地将一个整数右移一位等价于将这个数除以 2。
@ -120,7 +121,7 @@ let outputBits = firstBits ^ otherBits // 等于 00010001
2. 任何因移动而超出整型存储范围的位都会被丢弃。
3.`0` 来填充移位后产生的空白位。
这种方法称为逻辑移位。
这种方法称为*逻辑移位*
以下这张图展示了 `11111111 << 1`(即把 `11111111` 向左移动 `1` 位),和 `11111111 >> 1`(即把 `11111111` 向右移动 `1` 位)的结果。蓝色的部分是被移位的,灰色的部分是被抛弃的,橙色的部分则是被填充进来的:
@ -179,7 +180,7 @@ let blueComponent = pink & 0x0000FF // blueComponent 是 0x99即 153
![Art/bitshiftSignedMinusFourValue_2x.png](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/bitshiftSignedMinusFourValue_2x.png "Art/bitshiftSignedMinusFourValue_2x.png")
负数的表示通常被称为二进制补码表示。用这种方法来表示负数乍看起来有点奇怪,但它有几个优点。
负数的表示通常被称为*二进制补码*表示。用这种方法来表示负数乍看起来有点奇怪,但它有几个优点。
首先,如果想对 `-1``-4` 进行加法运算,我们只需要将这两个数的全部 8 个比特位进行相加,并且将计算结果中超出 8 位的数值丢弃:
@ -187,11 +188,11 @@ let blueComponent = pink & 0x0000FF // blueComponent 是 0x99即 153
其次,使用二进制补码可以使负数的按位左移和右移运算得到跟正数同样的效果,即每向左移一位就将自身的数值乘以 2每向右一位就将自身的数值除以 2。要达到此目的对有符号整数的右移有一个额外的规则
* 当对整数进行按位右移运算时,遵循与无符号整数相同的规则,但是对于移位产生的空白位使用符号位进行填充,而不是用 `0`
* 当对整数进行按位右移运算时,遵循与无符号整数相同的规则,但是对于移位产生的空白位使用*符号位*进行填充,而不是用 `0`
![Art/bitshiftSigned_2x.png](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/bitshiftSigned_2x.png "Art/bitshiftSigned_2x.png")
这个行为可以确保有符号整数的符号位不会因为右移运算而改变,这通常被称为算术移位。
这个行为可以确保有符号整数的符号位不会因为右移运算而改变,这通常被称为*算术移位*
由于正数和负数的特殊存储方式,在对它们进行右移的时候,会使它们越来越接近 `0`。在移位的过程中保持符号位不变,意味着负整数在接近 `0` 的过程中会一直保持为负。
@ -266,9 +267,9 @@ signedOverflow = signedOverflow &- 1
<a name="precedence_and_associativity"></a>
## 优先级和结合性
运算符的优先级使得一些运算符优先于其他运算符,高优先级的运算符会先被计算。
运算符的*优先级*使得一些运算符优先于其他运算符,高优先级的运算符会先被计算。
结合性定义了相同优先级的运算符是如何结合的,也就是说,是与左边结合为一组,还是与右边结合为一组。可以将这意思理解为“它们是与左边的表达式结合的”或者“它们是与右边的表达式结合的”。
*结合性*定义了相同优先级的运算符是如何结合的,也就是说,是与左边结合为一组,还是与右边结合为一组。可以将这意思理解为“它们是与左边的表达式结合的”或者“它们是与右边的表达式结合的”。
在复合表达式的运算顺序中,运算符的优先级和结合性是非常重要的。举例来说,运算符优先级解释了为什么下面这个表达式的运算结果会是 `17`
@ -313,7 +314,7 @@ signedOverflow = signedOverflow &- 1
<a name="operator_functions"></a>
## 运算符函数
类和结构体可以为现有的运算符提供自定义的实现,这通常被称为运算符重载。
类和结构体可以为现有的运算符提供自定义的实现,这通常被称为*运算符重载*
下面的例子展示了如何为自定义的结构体实现加法运算符(`+`)。算术加法运算符是一个双目运算符,因为它可以对两个值进行运算,同时它还是中缀运算符,因为它出现在两个值中间。
@ -351,7 +352,7 @@ let combinedVector = vector + anotherVector
<a name="prefix_and_postfix_operators"></a>
### 前缀和后缀运算符
上个例子演示了一个双目中缀运算符的自定义实现。类与结构体也能提供标准单目运算符的实现。单目运算符只运算一个值。当运算符出现在值之前时,它就是前缀的(例如 `-a`),而当它出现在值之后时,它就是后缀的(例如 `b!`)。
上个例子演示了一个双目中缀运算符的自定义实现。类与结构体也能提供标准*单目运算符*的实现。单目运算符只运算一个值。当运算符出现在值之前时,它就是*前缀*的(例如 `-a`),而当它出现在值之后时,它就是*后缀*的(例如 `b!`)。
要实现前缀或者后缀运算符,需要在声明运算符函数的时候在 `func` 关键字之前指定 `prefix` 或者 `postfix` 修饰符:
@ -377,7 +378,7 @@ let alsoPositive = -negative
<a name="compound_assignment_operators"></a>
### 复合赋值运算符
复合赋值运算符将赋值运算符(`=`)与其它运算符进行结合。例如,将加法与赋值结合成加法赋值运算符(`+=`)。在实现的时候,需要把运算符的左参数设置成 `inout` 类型,因为这个参数的值会在运算符函数内直接被修改。
*复合赋值运算符*将赋值运算符(`=`)与其它运算符进行结合。例如,将加法与赋值结合成加法赋值运算符(`+=`)。在实现的时候,需要把运算符的左参数设置成 `inout` 类型,因为这个参数的值会在运算符函数内直接被修改。
```swift
extension Vector2D {
@ -403,7 +404,7 @@ original += vectorToAdd
<a name="equivalence_operators"></a>
### 等价运算符
自定义的类和结构体没有对等价运算符进行默认实现,等价运算符通常被称为“相等”运算符(`==`)与“不等”运算符(`!=`。对于自定义类型Swift 无法判断其是否“相等”,因为“相等”的含义取决于这些自定义类型在你的代码中所扮演的角色。
自定义的类和结构体没有对*等价运算符*进行默认实现,等价运算符通常被称为“相等”运算符(`==`)与“不等”运算符(`!=`。对于自定义类型Swift 无法判断其是否“相等”,因为“相等”的含义取决于这些自定义类型在你的代码中所扮演的角色。
为了使用等价运算符能对自定义的类型进行判等运算,需要为其提供自定义实现,实现的方法与其它中缀运算符一样:
@ -434,7 +435,7 @@ if twoThree == anotherTwoThree {
<a name="custom_operators"></a>
## 自定义运算符
除了实现标准运算符,在 Swift 中还可以声明和实现自定义运算符。可以用来自定义运算符的字符列表请参考[运算符](../chapter3/02_Lexical_Structure.html#operators)。
除了实现标准运算符,在 Swift 中还可以声明和实现*自定义运算符*。可以用来自定义运算符的字符列表请参考[运算符](../chapter3/02_Lexical_Structure.html#operators)。
新的运算符要使用 `operator` 关键字在全局作用域内进行定义,同时还要指定 `prefix``infix` 或者 `postfix` 修饰符: