Menu
CoddyTech

结构体还是类

本课属于 Coddy Swift 学习旅程的“面向对象编程”单元。第 10 课,共 57 课。

Swift 的指导原则是从 struct 开始,只有在需要类独有的功能时才选择类。结构体更简单:每个变量都拥有自己的值,因此在一个地方进行的更改不会让其他地方的代码感到意外。

struct Temperature {
    var celsius: Double
}

var today = Temperature(celsius: 21)
var yesterday = today
yesterday.celsius = 18
print(today.celsius)

输出:

21.0

当多个程序部分需要看到相同且不断变化的状态时,应选择类来共享一个对象,例如多个界面使用同一个银行账户。类还支持继承,而结构体不支持。

class SharedLog {
    var lines: [String] = []
}

let log = SharedLog()
let moduleA = log
let moduleB = log
moduleA.lines.append("A started")
moduleB.lines.append("B started")
print(log.lines.count)

输出:

2

结构体可以直接使用 ==。在声明中添加 Equatable,Swift 就会比较每个属性;而类使用 === 比较对象标识:

struct Point: Equatable {
    var x: Int
    var y: Int
}

print(Point(x: 1, y: 2) == Point(x: 1, y: 2))
print(Point(x: 1, y: 2) == Point(x: 2, y: 1))

输出:

true
false

快速判断一下:如果两个数据相同的项应该算作同一事物,就使用结构体(点、价格、日期)。如果一个项具有身份,即使它的数据与另一个项相同,这种身份仍然重要(用户账户、打开的文件),就使用类。

struct Money { var cents: Int }          // 500 美分就是 500 美分
class UserAccount {                      // 两个账户可以同名
    let id: Int
    var name: String
    init(id: Int, name: String) { self.id = id; self.name = name }
}
challenge icon

挑战

简单

Point 是一个应该支持使用 == 进行比较的结构体。为它添加协议遵循,并完成 countDistinct(_:),该函数会返回列表中不同点的数量(当两个点的坐标都相同时,它们就是同一个点)。

提供的代码会将每行读取为一个点,格式为 x,y,并输出 distinct: 和点的数量。

你的代码应写在 Point.swift 和 Functions.swift 中。main.swift 存放提供的输入/输出代码,不能编辑。

亲手试试

// 提供的输入和输出代码:保持原样。
var input: [String] = []
while let line = readLine() { input.append(line) }
let points = input.map { line -> Point in
    let p = line.split(separator: ",").map { Int($0)! }
    return Point(x: p[0], y: p[1])
}
print("distinct: \(countDistinct(points))")
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: Swift 在线编辑器