Swift 函数
函数是把"一段可复用逻辑"打包的基本单位。Swift 的函数特性丰富——参数标签、默认值、可变参数、inout、元组返回、函数类型……本章讲透每一个,并解释 Swift 设计背后的考量。
1. 基本语法
// 基本语法:func 名(参数) -> 返回类型 { 函数体 }
func add(a: Int, b: Int) -> Int {
return a + b
}
// 调用时必须写出第一个参数名(标签)
print(add(a: 3, b: 5)) // 8
// 没有返回值就省略 -> 或写成 -> Void
func sayHello() {
print("Hello!")
}
sayHello()
// 多语句函数,返回值用 return
func isEven(n: Int) -> Bool {
if n % 2 == 0 {
return true
}
return false
}
// 单表达式函数可省略 return(Swift 5+)
func square(_ x: Int) -> Int { x * x }几个要点:返回类型用 ->;没有返回值省略或写 Void;Swift 5+ 单表达式可省 return(让函数像数学公式一样简洁)。
2. 参数标签:Swift 函数的灵魂
Swift 函数最特别的一点是参数标签。调用时写出标签,让代码读起来像自然语言——这是从 Objective-C 继承的传统,但更克制:
// 参数标签:Swift 函数的灵魂
// 调用时写"标签"让代码像自然语言
// 1. 默认:形参名既是内部名也是外部标签
func greet(name: String) -> String {
return "Hi, \(name)"
}
greet(name: "小明") // 调用时写 name
// 2. 用 _ 省略外部标签(让调用更简洁)
func add(_ a: Int, _ b: Int) -> Int {
return a + b
}
add(2, 3) // 没有 a: b:
// 3. 内外名分开:外部名 内部名
func greet(name: String, from city: String) -> String {
return "\(name) 来自 \(city)" // 内部用 city
}
greet(name: "小明", from: "北京") // 外部用 from
// 经典例子:Swift 标准库的 remove(at:)
// [1,2,3].remove(at: 0) 读起来"remove at 0"三个核心模式:
- 默认有标签(形参名当标签):
greet(name: "小明")。 - 下划线
_省略标签:适合数学函数add(2, 3)。 - 内外名分开:
from city,外部叫 from,内部叫 city。
标准库的 remove(at:)、append(contentsOf:) 都是这种风格的典范——读起来像一句话。
3. 默认参数与可变参数
// 默认参数:调用时可省略
func makeCoffee(sugar: Int = 1, milk: Bool = true) -> String {
return "coffee, sugar=\(sugar), milk=\(milk)"
}
makeCoffee() // coffee, sugar=1, milk=true
makeCoffee(sugar: 3) // milk 默认 true
makeCoffee(sugar: 0, milk: false)
// 可变参数:同类型任意个,在函数内是数组
func sum(_ numbers: Int...) -> Int {
var total = 0
for n in numbers { total += n }
return total
}
print(sum(1, 2, 3, 4, 5)) // 15
print(sum()) // 0
// 注意:一个函数最多一个可变参数,且一般是最后一个默认参数让函数调用更灵活(同一个函数不同调用形式);可变参数让函数接受任意个相同类型参数,在函数内是数组。注意:一个函数最多一个可变参数,且通常是最后一个位置。
4. inout 参数
Swift 函数参数默认是常量(不能在函数内修改)。要让函数修改外部变量,用 inout,调用时加 &:
// inout:让函数能修改外部变量(类似 C 的指针传参)
func increment(_ n: inout Int) {
n += 1
}
var count = 0
increment(&count) // 注意 &
print(count) // 1
increment(&count)
print(count) // 2
// inout 用于"想要函数修改入参"的场景
// 但 Swift 推荐优先用返回值,inout 只用于性能关键场合
// 经典例子:swap
func swap(_ a: inout Int, _ b: inout Int) {
let t = a; a = b; b = t
}
var x = 1, y = 2
swap(&x, &y)
print(x, y) // 2 1Swift 推荐优先用返回值而非 inout,因为返回值更清晰、更易测试。inout 主要用于性能关键场合(避免大结构体拷贝)。
5. 多返回值:元组
Swift 没有专门的"多返回值"语法,但元组实现了一样的效果。给元组元素命名,调用方就能用点语法访问:
// 多返回值:用元组
func minMax(_ nums: [Int]) -> (min: Int, max: Int)? {
guard !nums.isEmpty else { return nil }
var lo = nums[0], hi = nums[0]
for n in nums {
if n < lo { lo = n }
if n > hi { hi = n }
}
return (lo, hi)
}
if let r = minMax([3, 1, 4, 1, 5, 9, 2, 6]) {
print("min=\(r.min), max=\(r.max)") // min=1, max=9
}
// @discardableResult:函数有返回值但调用方常忽略,加这个去掉警告
@discardableResult
func updateCounter() -> Int {
counter += 1
return counter
}
updateCounter() // 不接收返回值,无警告另一个常用注解 @discardableResult 告诉编译器"这个函数有返回值,但调用方忽略也没关系",消除警告。
6. 函数是一等公民
Swift 里函数是类型——可以赋值给变量、作为参数传递、作为返回值。函数类型写作 (参数类型) -> 返回类型:
// 函数也是一等公民:可赋值、传参、返回
func add(_ a: Int, _ b: Int) -> Int { a + b }
func mul(_ a: Int, _ b: Int) -> Int { a * b }
// 函数类型:(Int, Int) -> Int
var op: (Int, Int) -> Int = add
print(op(2, 3)) // 5
op = mul
print(op(2, 3)) // 6
// 函数作为参数(高阶函数)
func compute(_ a: Int, _ b: Int, using f: (Int, Int) -> Int) -> Int {
return f(a, b)
}
print(compute(2, 3, using: add)) // 5
// 函数作为返回值
func makeMultiplier(factor: Int) -> (Int) -> Int {
return { n in n * factor }
}
let double = makeMultiplier(factor: 2)
print(double(5)) // 10这种"函数当数据用"的能力是函数式编程的基础。Swift 的 map、filter、reduce 都依赖它——这些会在数组和闭包章深入讲。
7. 嵌套函数
函数内部还能再定义函数。嵌套函数对外不可见,但能"捕获"外层的变量:
// 嵌套函数:函数里再定义函数
func makeIncrementer(step: Int) -> () -> Int {
var total = 0
func inc() -> Int {
total += step
return total
}
return inc
}
let counter = makeIncrementer(step: 5)
print(counter()) // 5
print(counter()) // 10
print(counter()) // 15
// 嵌套函数能"捕获"外部变量(step、total)
// 这其实是闭包的一种,后面专章讲这其实是闭包的一种形式。下一章讲完可选类型,再下下章我们专门讲闭包。
8. 函数实战
- API 设计:给所有公开参数起清晰的标签,调用读起来应该像一句话。
- 参数太多(超过 5 个):考虑用 struct 包装参数。
- 避免副作用:能用返回值就别用 inout,能 immutable 就别 mutable。
- 命名约定:动词开头的方法表示动作(
fetchUser、sendMessage);名词开头表示返回值(userName、currentUser)。
小结
Swift 函数 = 基本语法 + 参数标签 + 默认/可变/inout 参数 + 元组返回 + 函数类型。其中参数标签是最具 Swift 味道的特性,值得反复品味。下一篇我们看 Swift 真正的杀手锏——可选类型。
← 上一篇 Swift 控制流
下一篇 Swift 可选类型 →