13
13
>
14
14
> 2.2
15
15
> 翻译+校对:[ SketchK] ( https://github.com/SketchK ) 2016-05-17
16
+ >
17
+ > 3.0
18
+ > 翻译+校对:[ mmoaay] ( https://github.com/mmoaay ) 2016-09-20
16
19
17
20
本页内容包括:
18
21
@@ -320,12 +323,15 @@ signedOverflow = signedOverflow &- 1
320
323
struct Vector2D {
321
324
var x = 0.0 , y = 0.0
322
325
}
323
- func + (left : Vector2D, right : Vector2D) -> Vector2D {
324
- return Vector2D (x : left.x + right.x , y : left.y + right.y )
326
+
327
+ extension Vector2D {
328
+ static func + (left : Vector2D, right : Vector2D) -> Vector2D {
329
+ return Vector2D (x : left.x + right.x , y : left.y + right.y )
330
+ }
325
331
}
326
332
```
327
333
328
- 该运算符函数被定义为一个全局函数 ,并且函数的名字与它要进行重载的 ` + ` 名字一致。因为算术加法运算符是双目运算符 ,所以这个运算符函数接收两个类型为 ` Vector2D ` 的参数,同时有一个 ` Vector2D ` 类型的返回值。
334
+ 该运算符函数被定义为 ` Vector2D ` 上的一个类方法 ,并且函数的名字与它要进行重载的 ` + ` 名字一致。因为加法运算并不是一个向量必需的功能,所以这个类方法被定义在 ` Vector2D ` 的一个扩展中,而不是 ` Vector2D ` 结构体声明内。而算术加法运算符是双目运算符 ,所以这个运算符函数接收两个类型为 ` Vector2D ` 的参数,同时有一个 ` Vector2D ` 类型的返回值。
329
335
330
336
在这个实现中,输入参数分别被命名为 ` left ` 和 ` right ` ,代表在 ` + ` 运算符左边和右边的两个 ` Vector2D ` 实例。函数返回了一个新的 ` Vector2D ` 实例,这个实例的 ` x ` 和 ` y ` 分别等于作为参数的两个实例的 ` x ` 和 ` y ` 的值之和。
331
337
@@ -350,8 +356,10 @@ let combinedVector = vector + anotherVector
350
356
要实现前缀或者后缀运算符,需要在声明运算符函数的时候在 ` func ` 关键字之前指定 ` prefix ` 或者 ` postfix ` 修饰符:
351
357
352
358
``` swift
353
- prefix func - (vector : Vector2D) -> Vector2D {
354
- return Vector2D (x : - vector.x , y : - vector.y )
359
+ extension Vector2D {
360
+ static prefix func - (vector : Vector2D) -> Vector2D {
361
+ return Vector2D (x : - vector.x , y : - vector.y )
362
+ }
355
363
}
356
364
```
357
365
@@ -372,8 +380,10 @@ let alsoPositive = -negative
372
380
复合赋值运算符将赋值运算符(` = ` )与其它运算符进行结合。例如,将加法与赋值结合成加法赋值运算符(` += ` )。在实现的时候,需要把运算符的左参数设置成 ` inout ` 类型,因为这个参数的值会在运算符函数内直接被修改。
373
381
374
382
``` swift
375
- func += (inout left : Vector2D, right : Vector2D) {
376
- left = left + right
383
+ extension Vector2D {
384
+ static func += (left : inout Vector2D, right : Vector2D) {
385
+ left = left + right
386
+ }
377
387
}
378
388
```
379
389
@@ -398,11 +408,13 @@ original += vectorToAdd
398
408
为了使用等价运算符能对自定义的类型进行判等运算,需要为其提供自定义实现,实现的方法与其它中缀运算符一样:
399
409
400
410
``` swift
401
- func == (left : Vector2D, right : Vector2D) -> Bool {
402
- return (left.x == right.x ) && (left.y == right.y )
403
- }
404
- func != (left : Vector2D, right : Vector2D) -> Bool {
405
- return ! (left == right)
411
+ extension Vector2D {
412
+ static func == (left : Vector2D, right : Vector2D) -> Bool {
413
+ return (left.x == right.x ) && (left.y == right.y )
414
+ }
415
+ static func != (left : Vector2D, right : Vector2D) -> Bool {
416
+ return ! (left == right)
417
+ }
406
418
}
407
419
```
408
420
@@ -430,47 +442,46 @@ if twoThree == anotherTwoThree {
430
442
prefix operator +++ {}
431
443
```
432
444
433
- 上面的代码定义了一个新的名为 ` +++ ` 的前缀运算符。对于这个运算符,在 Swift 中并没有意义,因此我们针对 ` Vector2D ` 的实例来定义它的意义。对这个示例来讲,` +++ ` 被实现为“前缀双自增”运算符。它使用了前面定义的复合加法运算符来让矩阵对自身进行相加,从而让 ` Vector2D ` 实例的 ` x ` 属性和 ` y ` 属性的值翻倍:
445
+ 上面的代码定义了一个新的名为 ` +++ ` 的前缀运算符。对于这个运算符,在 Swift 中并没有意义,因此我们针对 ` Vector2D ` 的实例来定义它的意义。对这个示例来讲,` +++ ` 被实现为“前缀双自增”运算符。它使用了前面定义的复合加法运算符来让矩阵对自身进行相加,从而让 ` Vector2D ` 实例的 ` x ` 属性和 ` y ` 属性的值翻倍。实现 ` +++ ` 运算符的方式如下 :
434
446
435
447
``` swift
436
- prefix func +++ (inout vector : Vector2D) -> Vector2D {
437
- vector += vector
438
- return vector
448
+ extension Vector2D {
449
+ static prefix func +++ (vector : inout Vector2D) -> Vector2D {
450
+ vector += vector
451
+ return vector
452
+ }
439
453
}
440
- ```
441
454
442
- ` Vector2D ` 的 ` +++ ` 的实现和 ` ++ ` 的实现很相似,唯一不同的是前者对自身进行相加,而后者是与另一个值为 ` (1.0, 1.0) ` 的向量相加。
443
455
444
- ``` swift
445
456
var toBeDoubled = Vector2D (x : 1.0 , y : 4.0 )
446
457
let afterDoubling = +++ toBeDoubled
447
458
// toBeDoubled 现在的值为 (2.0, 8.0)
448
459
// afterDoubling 现在的值也为 (2.0, 8.0)
449
460
```
450
461
451
462
<a name =" precedence_and_associativity_for_custom_infix_operators " ></a >
452
- ### 自定义中缀运算符的优先级和结合性
453
-
454
- 自定义的中缀运算符也可以指定优先级和结合性。[ 优先级和结合性] ( #precedence_and_associativity ) 中详细阐述了这两个特性是如何对中缀运算符的运算产生影响的。
463
+ ### 自定义中缀运算符的优先级
455
464
456
- 结合性可取的值有 ` left ` , ` right ` 和 ` none ` 。当左结合运算符跟其他相同优先级的左结合运算符写在一起时,会跟左边的值进行结合。同理,当右结合运算符跟其他相同优先级的右结合运算符写在一起时,会跟右边的值进行结合。而非结合运算符不能跟其他相同优先级的运算符写在一起 。
465
+ 每个自定义中缀运算符都属于某个优先级组。这个优先级组指定了这个运算符和其他中缀运算符的优先级和结合性。 [ 优先级和结合性 ] ( #precedence_and_associativity ) 中详细阐述了这两个特性是如何对中缀运算符的运算产生影响的 。
457
466
458
- 结合性的默认值是 ` none ` ,优先级的默认值 ` 100 ` 。
467
+ 而没有明确放入优先级组的自定义中缀运算符会放到一个默认的优先级组内,其优先级高于三元运算符 。
459
468
460
- 以下例子定义了一个新的中缀运算符 ` +- ` ,此运算符的结合性为 ` left ` ,并且它的优先级为 ` 140 ` :
469
+ 以下例子定义了一个新的自定义中缀运算符 ` +- ` ,此运算符属于 ` AdditionPrecedence ` 优先组 :
461
470
462
471
``` swift
463
- infix operator +- { associativity left precedence 140 }
464
- func +- (left : Vector2D, right : Vector2D) -> Vector2D {
465
- return Vector2D (x : left.x + right.x , y : left.y - right.y )
472
+ infix operator +- : AdditionPrecedence
473
+ extension Vector2D {
474
+ static func +- (left : Vector2D, right : Vector2D) -> Vector2D {
475
+ return Vector2D (x : left.x + right.x , y : left.y - right.y )
476
+ }
466
477
}
467
478
let firstVector = Vector2D (x : 1.0 , y : 2.0 )
468
479
let secondVector = Vector2D (x : 3.0 , y : 4.0 )
469
480
let plusMinusVector = firstVector +- secondVector
470
481
// plusMinusVector 是一个 Vector2D 实例,并且它的值为 (4.0, -2.0)
471
482
```
472
483
473
- 这个运算符把两个向量的 ` x ` 值相加,同时用第一个向量的 ` y ` 值减去第二个向量的 ` y ` 值。因为它本质上是属于“相加型”运算符,所以将它的结合性和优先级被分别设置为 ` left ` 和 ` 140 ` ,这与 ` + ` 和 ` - ` 等默认的中缀“相加型”运算符是相同的 。关于 Swift 标准库提供的运算符的结合性与优先级, 请参考 [ Swift Standard Library Operators Reference] ( https://developer.apple.com/library/prerelease/ios/documentation/Swift/Reference/Swift_StandardLibrary_Operators/index.html#//apple_ref/doc/uid/TP40016054 ) 。
484
+ 这个运算符把两个向量的 ` x ` 值相加,同时用第一个向量的 ` y ` 值减去第二个向量的 ` y ` 值。因为它本质上是属于“相加型”运算符,所以将它放置 ` + ` 和 ` - ` 等默认的中缀“相加型”运算符相同的优先级组中 。关于 Swift 标准库提供的运算符,以及完整的运算符优先级组和结合性设置, 请参考 [ Swift Standard Library Operators Reference] ( https://developer.apple.com/library/prerelease/ios/documentation/Swift/Reference/Swift_StandardLibrary_Operators/index.html#//apple_ref/doc/uid/TP40016054 ) 。而更多关于优先级组以及自定义操作符和优先级组的语法,请参考 [ 运算符声明 ] ( #operator_declaration )
474
485
475
486
> 注意
476
487
> 当定义前缀与后缀运算符的时候,我们并没有指定优先级。然而,如果对同一个值同时使用前缀与后缀运算符,则后缀运算符会先参与运算。
0 commit comments