可失败的初始化器
本课属于 Coddy Swift 学习旅程的“面向对象编程”单元。第 20 课,共 57 课。
有些值无法根据所有输入构建。可失败初始化器写作 init?,当输入无效时,它会返回 nil,而不是返回一个实例,因此无效实例永远不会存在:
struct Percentage {
let value: Int
init?(_ value: Int) {
guard value >= 0, value <= 100 else { return nil }
self.value = value
}
}
print(Percentage(42)?.value ?? -1)
print(Percentage(150)?.value ?? -1)输出:
42
-1可失败初始化器的结果是一个可选值,因此调用方必须对其进行解包,通常使用 if let 或 guard let:
struct Email {
let address: String
init?(_ text: String) {
let parts = text.split(separator: "@")
guard parts.count == 2, parts[1].contains(".") else { return nil }
address = text.lowercased()
}
}
for text in ["Ada@Mail.com", "not-an-email"] {
if let email = Email(text) {
print("valid: \(email.address)")
} else {
print("invalid: \(text)")
}
}输出:
valid: ada@mail.com
invalid: not-an-emailSwift 自带的类型也使用相同的思路:Int("42") 和 Double("x") 都是可失败初始化器,枚举的 init(rawValue:) 也是如此。可失败初始化器可以调用这些初始化器,并传递失败结果:
struct Coordinate {
let lat: Double
let lon: Double
init?(text: String) {
let parts = text.split(separator: ",")
guard parts.count == 2,
let lat = Double(parts[0]), let lon = Double(parts[1]),
abs(lat) <= 90, abs(lon) <= 180 else { return nil }
self.lat = lat
self.lon = lon
}
}
print(Coordinate(text: "51.5,-0.1") != nil)
print(Coordinate(text: "95,10") != nil)输出:
true
false如果缺少值这一信息就足够了,请使用 init?。如果调用方需要知道哪条规则未通过,请使用会抛出异常的初始化器 init(...) throws:
struct Username {
let text: String
init(_ text: String) throws {
guard text.count >= 3 else { throw NameError.tooShort }
guard text.allSatisfy({ $0.isLetter }) else { throw NameError.badCharacters }
self.text = text
}
}挑战
简单请补全结构体 Rgb,它将颜色存储为 red、green 和 blue,每个值的范围是 0 到 255。它的可失败初始化器 init?(hex:) 会读取类似 #FF8000 的文本:只有当文本是 # 后面恰好跟着六个十六进制数字时,才会返回非 nil 的值。对每一对数字使用 Int(text, radix: 16)。添加一个计算属性 label,使其返回 rgb(255, 128, 0)。
提供的代码会逐行读取颜色,并打印标签或 invalid: text。
你的代码写在 Rgb.swift 中。main.swift 包含提供的输入/输出代码,不能编辑。
亲手试试
// 提供的输入/输出代码:保持原样。
var input: [String] = []
while let line = readLine() { input.append(line) }
for line in input {
if let color = Rgb(hex: line) {
print(color.label)
} else {
print("invalid: \(line)")
}
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Swift 在线编辑器