方法(Method)

  • 枚举、结构体、类都可以定义实例方法、类型方法
    1. 实例方法(Instance Method):通过实例对象调用
    2. 类型方法(Type Method):通过类型调用,用 static 或者 class 关键字定义
1
2
3
4
5
6
7
8
9
10
11
class Car {
static var cout = 0
init() {
Car.cout += 1
}
static func getCout() -> Int { cout }
}
let c0 = Car()
let c1 = Car()
let c2 = Car()
print(Car.getCout()) // 3
  • self

    • 在实例方法中代表实例对象
    • 在类型方法中代表类型
  • 在类型方法static func getCount中,cout.cout, Car.self.cout, Car.cout

mutating

  • 结构体和枚举是值类型,默认情况下,值类型的属性不能被自身的实例方法修改
  • 在func关键字前加 mutating 可以允许这种修改行为
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    struct Point {
    var x = 0.0, y = 0.0
    mutating func moveBy(deltaX: Double, deltaY: Double) {
    x += deltaX
    y += deltaY
    // self = Point(x: x + deltaX, y: y + deltaY)
    }
    }

    enum StateSwitch {
    case low, middle, high
    mutating func next() {
    switch self {
    case .low:
    self = .middle
    case .middle:
    self = .high
    case .high:
    self = .low
    }
    }
    }

@discardableResult

在func前面加个@discardableResult,可以消除,函数调用后返回值未被使用的警告

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct Point {
var x = 0.0, y = 0.0
@discardableResult mutating
func moveX(deltaX: Double) -> Double {
x += deltaX
return x
}
}
var p = Point()
p.moveX(deltaX: 10)

@discardableResult
func get() -> Int {
return 10
}
get()

下标(subscript)

  • 使用subscript可以给任意类型(枚举、结构体、类)增加下标功能,有些地方也翻译为:下标脚本

  • subscript的语法类似于实例方法、计算属性,本质就是方法(函数)

    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
    class Point {
    var x = 0.0, y = 0.0
    subscript(index: Int) -> Double {
    set {
    if index ` 0 {
    x = newValue
    } else if index ` 1 {
    y = newValue
    }
    }
    get {
    if index ` 0 {
    return x
    } else if index ` 1 {
    return y
    }
    return 0
    }
    }
    }

    var p = Point()
    p[0] = 11.1
    p[1] = 22.2
    print(p.x) // 11.1
    print(p.y) // 22.2
    print(p[0]) // 11.1
    print(p[1]) // 22.2
  • subscript中定义的返回值类型决定了

    • get方法的返回值类型
    • set方法中newValue的类型
  • subscript可以接受多个参数,并且类型任意

下标细节

subscript可以没有set方法,但必须有get方法

1
2
3
4
5
6
7
8
9
10
11
12
13
class Point {
var x = 0.0, y = 0.0
subscript(index: Int) -> Double {
get {
if index ` 0 {
return x
} else if index ` 1 {
return y
}
return 0
}
}
}
  • 如果只有get方法,可以省略get关键字
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class Point {
    var x = 0.0, y = 0.0
    subscript(index: Int) -> Double {
    if index ` 0 {
    return x
    } else if index ` 1 {
    return y
    }
    return 0
    }
    }

可以设置参数标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Point {
var x = 0.0, y = 0.0
subscript(index i: Int) -> Double {
if i ` 0 {
return x
} else if i ` 1 {
return y
}
return 0
}
}

var p = Point()
p.y = 22.2
print(p[index: 1]) // 22.2

下标可以是类型方法

1
2
3
4
5
6
class Sum {
static subscript(v1: Int, v2: Int) -> Int {
return v1 + v2
}
}
print(Sum[10, 20]) // 30

结构体、类作为返回值对比

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
// 类作为返回值 
class Point {
var x = 0, y = 0
}
class PointManager {
var point = Point()
subscript(index: Int) -> Point {
get { point }
}
}
var pm = PointManager()
pm[0].x = 11
pm[0].y = 22
// Point(x: 11, y: 22)
print(pm[0])
// Point(x: 11, y: 22)
print(pm.point)

// 结构体作为返回值
struct Point {
var x = 0, y = 0
}
class PointManager {
var point = Point()
subscript(index: Int) -> Point {
set { point = newValue }
get { point }
}
}

接收多个参数的下标

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
class Grid {
var data = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8] ]
subscript(row: Int, column: Int) -> Int {
set {
guard row >= 0 && row < 3 && column >= 0 && column < 3 else {
return
}
data[row][column] = newValue
}
get {
guard row >= 0 && row < 3 && column >= 0 && column < 3 else {
return 0
}
return data[row][column]
}
}
}

var grid = Grid()
grid[0, 1] = 77
grid[1, 2] = 88
grid[2, 0] = 99
print(grid.data)

参考

  • 李明杰老师课件