Swift Protocols(协议)、Extensions(扩展)、Error Handling(错误处理)、Generics(泛型)
最近在学习 Swift,总结相关知识
1. Protocols(协议)
1.1 协议的定义和实现
- 协议(
protocol
) 是一种定义方法和属性的蓝图,任何类、结构体或枚举都可以遵循协议。 - 遵循协议后,需要实现协议中定义的所有内容。
示例
protocol ExampleProtocol {
var simpleDescription: String { get }
mutating func adjust()
}
simpleDescription
: 定义了一个只读属性。mutating
: 标记方法可以修改遵循协议的值类型(如结构体、枚举)。
实现协议
-
类(
class
) 遵循协议:class SimpleClass: ExampleProtocol { var simpleDescription: String = "A very simple class." var anotherProperty: Int = 69105 func adjust() { simpleDescription += " Now 100% adjusted." } }
- 方法
adjust
可以直接修改属性,无需标记为mutating
。
- 方法
-
结构体(
struct
) 遵循协议:struct SimpleStructure: ExampleProtocol { var simpleDescription: String = "A simple structure" mutating func adjust() { simpleDescription += " (adjusted)" } }
mutating
必须添加,因为结构体是值类型,默认情况下,方法不能修改实例。
1.2 扩展协议要求
向协议 ExampleProtocol
添加新的要求:
protocol ExampleProtocol {
var simpleDescription: String { get }
mutating func adjust()
func detailedDescription() -> String
}
class SimpleClass: ExampleProtocol {
var simpleDescription: String = "A very simple class."
func adjust() {
simpleDescription += " Now 100% adjusted."
}
func detailedDescription() -> String {
return "This is \(simpleDescription)"
}
}
struct SimpleStructure: ExampleProtocol {
var simpleDescription: String = "A simple structure"
mutating func adjust() {
simpleDescription += " (adjusted)"
}
func detailedDescription() -> String {
return "This is \(simpleDescription)"
}
}
2. Extensions(扩展)
2.1 扩展定义
扩展可以用来为现有的类、结构体、枚举或协议添加功能,例如添加方法、计算属性或协议一致性。
示例:扩展 Int
extension Int: ExampleProtocol {
var simpleDescription: String {
return "The number \(self)"
}
mutating func adjust() {
self += 42
}
}
print(7.simpleDescription) // 输出:The number 7
实验:扩展 Double
添加 absoluteValue
extension Double {
var absoluteValue: Double {
return self >= 0 ? self : -self
}
}
print((-3.14).absoluteValue) // 输出:3.14
3. Error Handling(错误处理)
3.1 错误类型
- Swift 的错误类型必须遵循
Error
协议,通常用enum
定义。
enum PrinterError: Error {
case outOfPaper
case noToner
case onFire
}
3.2 抛出和捕获错误
- 使用
throw
抛出错误,使用throws
标记函数可能抛出错误。 - 使用
do-catch
捕获错误。
示例
func send(job: Int, toPrinter printerName: String) throws -> String {
if printerName == "Never Has Toner" {
throw PrinterError.noToner
}
return "Job sent"
}
do {
let printerResponse = try send(job: 1040, toPrinter: "Bi Sheng")
print(printerResponse)
} catch PrinterError.noToner {
print("No toner available.")
} catch {
print(error)
}
3.3 使用 try?
和 defer
try?
: 抛出错误时返回nil
。defer
: 无论函数是否抛出错误,都执行清理代码。
示例
let printerSuccess = try? send(job: 1884, toPrinter: "Mergenthaler")
let printerFailure = try? send(job: 1885, toPrinter: "Never Has Toner")
func fridgeContains(_ food: String) -> Bool {
defer { print("Fridge closed.") } // 确保清理
return ["milk", "eggs"].contains(food)
}
4. Generics(泛型)
4.1 泛型函数
- 泛型允许编写通用代码,支持多种类型。
func makeArray<Item>(repeating item: Item, numberOfTimes: Int) -> [Item] {
var result: [Item] = []
for _ in 0..<numberOfTimes {
result.append(item)
}
return result
}
makeArray(repeating: "knock", numberOfTimes: 4)
4.2 泛型类型
- 例如,重新实现 Swift 标准库的
Optional
类型:
enum OptionalValue<Wrapped> {
case none
case some(Wrapped)
}
var possibleInteger: OptionalValue<Int> = .none
possibleInteger = .some(100)
4.3 泛型约束
- 使用
where
指定类型约束。
func anyCommonElements<T: Sequence, U: Sequence>(_ lhs: T, _ rhs: U) -> Bool
where T.Element: Equatable, T.Element == U.Element {
for lhsItem in lhs {
for rhsItem in rhs {
if lhsItem == rhsItem {
return true
}
}
}
return false
}
anyCommonElements([1, 2, 3], [3])
实验:返回公共元素数组
func commonElements<T: Sequence, U: Sequence>(_ lhs: T, _ rhs: U) -> [T.Element]
where T.Element: Equatable, T.Element == U.Element {
var result: [T.Element] = []
for lhsItem in lhs {
if rhs.contains(lhsItem) {
result.append(lhsItem)
}
}
return result
}
print(commonElements([1, 2, 3], [3, 4, 5])) // 输出:[3]
总结
Swift 提供了许多现代化特性:
- Protocols 和 Extensions: 提供灵活的功能扩展和一致性约束。
- Error Handling: 提供
throw
、do-catch
、try?
等灵活的错误处理机制。 - Generics: 支持编写通用、高效、类型安全的代码。
- 类型安全性: Swift 的类型系统可以有效防止运行时错误,提升代码可靠性。