if let planet = Planet(rawValue: 3) {
print("Planet with raw value 3 is \(planet)") // 输出: Planet with raw value 3 is earth
} else {
print("No planet found with that raw value.")
}
在学习枚举时,发现可以使用init?(rawValue:)通过原始值创建枚举实例。如果给定的值没有对应的枚举case,则会返回nil,这是一个可失败的初始化,因此引出了本篇的科普文《可失败的构造函数》。
什么是可失败的构造函数
在 Swift 中,可失败的构造函数是一种特殊的构造函数,用于在某些情况下可能无法成功创建对象实例时使用。如果初始化失败,则返回 nil。可失败的构造函数在声明时使用 ? 表示,具体形式如下:
init?()
何时使用可失败的构造函数
1、初始化可能失败的情况:
当某个类、结构体或枚举在初始化时无法保证总是成功创建对象时,可以使用可失败的构造函数。例如,从不合法的输入创建对象时,或者当资源不足时,就可以返回 nil 来表示初始化失败。
2.、输入值验证:
在初始化时进行验证,如果输入的参数不符合要求,则返回 nil。
示例 1: 字符串到整数的转换
Swift 提供了一个内建的可失败构造函数 Int(string:),用于从字符串中解析整数:
let validNumber = Int("123") // 返回 Optional(123)
let invalidNumber = Int("abc") // 返回 nil,因为 "abc" 不是有效的整数
在这个例子中,如果传入的字符串无法转换成整数,Int 构造函数会返回 nil。
示例 2: 自定义可失败构造函数
假设我们有一个结构体 Person,它只有在年龄合法(即 0 到 150 之间)时才允许创建:
struct Person {
let name: String
let age: Int
init?(name: String, age: Int) {
if age < 0 || age > 150 {
return nil // 年龄不合法,初始化失败
}
self.name = name
self.age = age
}
}
if let person = Person(name: "方君宇", age: 30) {
print("成功创建:\(person.name), \(person.age) 岁") // 输出: 成功创建:方君宇, 30 岁
} else {
print("初始化失败")
}
if let invalidPerson = Person(name: "方君宇", age: 200) {
print("成功创建:\(invalidPerson.name), \(invalidPerson.age) 岁")
} else {
print("初始化失败") // 输出: 初始化失败
}
如果尝试将init后面的可选类型?删除的话:
init(name: String, age: Int) {
Xcode会在return nil行报错:
return nil // 报错行
报错内容为:
Only a failable initializer can return 'nil'
Use 'init?' to make the initializer 'init(name:age:)' failable
这表示只有可失败的初始化程序才能返回“nil”,因此推荐使用init?使初始化程序init(name:age)可失败。
在这个例子中,如果年龄超出了合理范围,构造函数就会返回 nil。
示例 3: 枚举中的可失败构造函数
可失败的构造函数常用于从原始值创建枚举实例,例如:
enum TemperatureUnit: Character {
case celsius = "C"
case fahrenheit = "F"
case kelvin = "K"
init?(symbol: Character) {
switch symbol {
case "C":
self = .celsius
case "F":
self = .fahrenheit
case "K":
self = .kelvin
default:
return nil // 非法符号,初始化失败
}
}
}
let unit = TemperatureUnit(symbol: "F") // 返回 .fahrenheit
let unknownUnit = TemperatureUnit(symbol: "X") // 返回 nil
总结
可失败的构造函数用于在初始化可能失败时提供一种优雅的处理方法。
它们返回一个可选类型(Optional),在成功时会包含实例,在失败时会返回 nil。
这使得在处理非法输入、资源不足或其他错误情况时,代码更加简洁和安全。