高级运算符
溢出运算符(Overflow Operator)
- Swift的算数运算符出现溢出时会抛出运行时错误
- Swift有溢出运算符(&+、&-、&*),用来支持溢出运算
swift
// 比如下面的代码,UInt8.max最大值是255,如果再+1就会出现溢出崩溃
var a = UInt8.max
print(a + 1)
print(a &+ 1) //使用溢出运算不会导致崩溃 结果为01
2
3
4
2
3
4
运算符重载(Operator Overload)
- 类、结构体、枚举可以为现有的运算符提供自定义的实现,这个操作叫做:运算符重载swift
struct Point { var x: Int, y: Int // 运算符重载, + 号放在两个中间 static func + (p1: Point, p2: Point) -> Point { Point(x: p1.x + p2.x, y: p1.y + p2.y) } // 使用 inout 改变传入参数的值 static func += (p1: inout Point, p2: Point) { p1 = p1 + p2 } // 运算法放在前面 static prefix func - (p: Point) -> Point { Point(x: -p.x, y: -p.y) } // 运算法放在后面 static postfix func ++ (p: inout Point) -> Point { let tmp = p p += Point(x: 1, y: 1) return tmp } } let p = Point(x: 10, y: 20) + Point(x: 11, y: 22) print(p) // Point(x: 21, y: 42)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Equatable 2个实例是否等价
要想得知2个实例是否等价,一般做法是遵守 Equatable 协议,重载 == 运算符。与此同时,等价于重载了 !=运算符。
swift
class Person: Equatable{
var age: Int = 0
init(age: Int) {
self.age = age
}
static func == (lhs: Person, rhs: Person) -> Bool {
lhs.age == rhs.age
}
}
let p1 = Person(age: 10)
let p2 = Person(age: 10)
print(p1 == p2)1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
Swift为以下类型提供默认的 Equatable 实现
markdown
1. 没有关联类型的枚举
2. 只拥有遵守 `Equatable` 协议关联类型的枚举
3. 只拥有遵守 `Equatable` 协议存储属性的结构体1
2
3
2
3
引用类型比较存储的地址值是否相等(是否引用着同一个对象),使用恒等运算符 === 、!==
Comparable 比较大小
要想比较2个实例的大小,一般做法是遵守 Comparable 协议,重载相应的运算符。Comparable比较大小有3种结果: 左边的参数大、相等、右边的参数大
swift
//定义的规则 score大的比较大,若score相等,age小的比较大
struct Student : Comparable {
var age: Int
var score: Int
init(score: Int, age: Int) {
self.score = score
self.age = age
}
static func < (lhs: Student, rhs: Student) -> Bool {
(lhs.score < rhs.score)
|| (lhs.score == rhs.score && lhs.age > rhs.age)
}
static func > (lhs: Student, rhs: Student) -> Bool {
(lhs.score > rhs.score)
|| (lhs.score == rhs.score && lhs.age < rhs.age)
}
static func <= (lhs: Student, rhs: Student) -> Bool {
!(lhs > rhs)
}
static func >= (lhs: Student, rhs: Student) -> Bool {
!(lhs < rhs)
}
}
var stu1 = Student(score: 100, age: 20)
var stu2 = Student(score: 98, age: 18)
var stu3 = Student(score: 100, age: 20)
print(stu1 > stu2) // true
print(stu1 >= stu2) // true
print(stu1 >= stu3) // true
print(stu1 <= stu3) // true
print(stu2 < stu1) // true
print(stu2 <= stu1) // true1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
自定义运算符(Custom Operator)
可以自定义新的运算符:在全局作用域使用operator进行声明。
markdown
* `prefix operator` 前缀运算符
* `postfix operator` 后缀运算符
* `infix operator` 中缀运算符 : 优先级组
precedencegroup 优先级组 {
associativity: 结合性(left\right\none) 从左到右还是从右到左
higherThan: 比谁的优先级高
lowerThan: 比谁的优先级低
assignment: true代表在可选链操作中拥有跟赋值运算符一样的优先级
}1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
示例如下:
swift
prefix operator +++
infix operator +- : PlusMinusPrecedence
precedencegroup PlusMinusPrecedence {
associativity: none
higherThan: AdditionPrecedence
lowerThan: MultiplicationPrecedence
assignment: true
}
struct Point {
var x: Int, y: Int
static prefix func +++ (point: inout Point) -> Point {
point = Point(x: point.x + point.x, y: point.y + point.y)
return point
}
static func +- (left: Point, right: Point) -> Point {
return Point(x: left.x + right.x, y: left.y - right.y)
}
static func +- (left: Point?, right: Point) -> Point {
print("+-")
return Point(x: left?.x ?? 0 + right.x, y: left?.y ?? 0 - right.y)
}
}
struct Person {
var point: Point
}
var person: Person? = nil
person?.point +- Point(x: 10, y: 20)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29