100 Days of Swift 学习笔记:Day7 吃透函数核心,从封装逻辑到返回多值
Day7 正式进入 Swift “代码复用核心区”—— 函数。函数能把重复的代码片段封装成一个 “工具”,不仅能减少重复编写,还能让代码更模块化(比如把 “掷骰子”“判断字符串字母是否相同” 做成函数,后续直接调用)。今天学了函数的定义、参数配置、返回值(包括多值返回的元组),还有外部参数名的实用技巧,整理了实操代码和场景对比,新手朋友跟着练能快速掌握 “代码封装” 的思路~
目录
一、函数基础:把代码片段封装成 “可调用工具”
函数的核心是 “输入(参数)→ 处理 → 输出(返回值)”,先从最简单的 “无参数、无返回值” 函数入手,理解基本结构。
1. 无参数、无返回值函数
// 定义函数:func 函数名() { 函数体 }
func showWelcome() {
print("Welcome to my app!")
print("This is a Swift learning tool.")
}
// 调用函数:函数名()
showWelcome()
- 关键结构:
func:Swift 中定义函数的关键字,必须放在最前面;showWelcome:函数名,遵循 “小驼峰命名法”(首字母小写,后续单词首字母大写);():参数列表,这里无参数,所以为空;{}:函数体,存放要执行的代码,和循环、条件的花括号逻辑一致。
- 适用场景:执行固定操作(如打印欢迎语、初始化配置),不需要定制化和返回结果。
二、带参数的函数:让函数更灵活(可定制化)
如果函数需要 “根据不同输入做不同处理”(比如打印不同数字的乘法表),就需要给函数加 “参数”—— 参数是函数的 “配置选项”,调用时必须传入对应类型的值。
1. 单个参数函数
// 定义函数:func 函数名(参数名: 参数类型) { 函数体 }
func printTimesTables(number: Int) {
for i in 1...12 {
print("\(i) * \(number) is \(i * number)")
}
}
// 调用函数:函数名(参数名: 具体值)
printTimesTables(number: 5) // 打印 5 的 1-12 乘法表
- 注意:Swift 调用函数时,必须写 “参数名:值” 的格式(比如
number: 5),这样能清晰区分多个参数的含义,避免混淆。
2. 多个参数函数
如果需要多个配置选项(比如自定义乘法表的结束数字),可以加多个参数,用逗号分隔:
// 定义函数:多个参数用逗号分隔
func printTimesTables(number: Int, end: Int) {
for i in 1...end { // end 参数控制乘法表的结束数字
print("\(i) x \(number) is \(i * number)")
}
}
// 调用函数:按定义顺序传入多个参数
printTimesTables(number: 5, end: 20) // 打印 5 的 1-20 乘法表
- 避坑点:参数顺序必须和函数定义时一致(比如不能先传
end再传number),否则会导致逻辑错误。 - 小知识:函数内部创建的变量 / 常量(如循环中的
i),会在函数执行完后自动销毁,外部无法访问(这叫 “作用域”,避免变量污染)。
三、带返回值的函数:让函数 “输出结果”
很多时候函数需要 “返回处理结果”(比如掷骰子返回点数、判断两个字符串是否字母相同),这时候需要明确 “返回值类型”,并用 return 关键字返回结果。
1. 基础返回值(单个值)
// 定义函数:func 函数名() -> 返回值类型 { 函数体 + return 结果 }
// 例子1:掷6面骰子,返回随机点数
func rollDice() -> Int {
return Int.random(in: 1...6) // 返回 1-6 的随机整数
}
// 调用函数:用变量接收返回值
let diceResult = rollDice()
print("掷出的点数:\(diceResult)")
// 例子2:判断两个字符串是否字母相同(忽略顺序)
func areLettersIdentical(string1: String, string2: String) -> Bool {
// 字符串排序后比较,相同则字母相同
return string1.sorted() == string2.sorted()
}
let isSame = areLettersIdentical(string1: "acb", string2: "abc")
print("字母是否相同:\(isSame)") // 输出 true
- 关键语法:
-> 返回值类型(比如-> Int)告诉 Swift 函数要返回什么类型的数据;return后面跟具体的返回值,执行到return时函数会立即结束。
2. 简化写法:单句函数可省略 return
如果函数体只有一行代码,且这行代码就是返回值,Swift 允许省略 return,代码更简洁:
// 简化前:有 return
func rollDice() -> Int {
return Int.random(in: 1...6)
}
// 简化后:无 return(仅单句代码可用)
func rollDice() -> Int {
Int.random(in: 1...6)
}
// 同理,判断字符串的函数也能简化
func areLettersIdentical(string1: String, string2: String) -> Bool {
string1.sorted() == string2.sorted()
}
四、返回多值:用元组解决 “返回多个结果” 的需求
如果函数需要返回多个值(比如返回用户的 “firstName” 和 “ lastName ”),用数组或字典会有缺陷(数组靠索引难记、字典需要默认值),这时元组是最优解 —— 元组能固定存储多个值,支持命名,且类型安全。
1. 用元组返回多值
// 定义函数:返回值类型是 (键1: 类型1, 键2: 类型2) 的元组
func getUser() -> (firstName: String, lastName: String) {
// 返回元组,键名可省略(Swift 会自动匹配定义的键名)
("Taylor", "Swift")
}
// 调用函数:用变量接收元组,通过键名访问值
let user = getUser()
print("姓名:\(user.firstName) \(user.lastName)") // 输出 Taylor Swift
- 元组的优势(对比数组 / 字典):
容器类型 优点 缺点 数组 简单 靠索引访问(难记,比如 user [0] 不知道是 firstName) 字典 键名清晰 需提供默认值(Swift 无法保证键一定存在) 元组 键名清晰、无需默认值、类型固定 大小固定(不能动态添加元素)
2. 元组的其他用法
- 无键名元组:如果不需要键名,可直接写类型,用索引访问(不推荐,可读性差):
func getUser() -> (String, String) { ("Taylor", "Swift") } let user = getUser() print("姓名:\(user.0) \(user.1)") // 用索引 0、1 访问 - 忽略不需要的值:如果只需要元组的部分值,用
_忽略其他值:let (firstName, _) = getUser() // 只取 firstName,忽略 lastName print("名:\(firstName)") // 输出 Taylor
五、函数参数的进阶:外部参数名(优化调用体验)
默认情况下,函数的参数名既是 “内部名”(函数内部使用)也是 “外部名”(调用时使用),但有时为了让调用更直观,需要自定义 “外部名”—— 比如 printTimesTables(for: 5) 比 printTimesTables(number: 5) 更易读。
1. 自定义外部参数名
// 定义函数:参数名前加“外部名 ”,格式为 外部名 内部名: 类型
func printTimesTables(for number: Int) {
// 函数内部用内部名 number
for i in 1...12 {
print("\(i) x \(number) is \(i * number)")
}
}
// 调用函数:用外部名 for
printTimesTables(for: 5) // 可读性更高:“为 5 打印乘法表”
2. 忽略外部参数名(用 _)
如果参数含义很明显(比如 append(_:) 向数组加元素),可以用 _ 忽略外部名,调用时不用写参数名:
// 定义函数:用 _ 忽略外部名,格式为 _ 内部名: 类型
func isUppercase(_ string: String) -> Bool {
string == string.uppercased() // 判断字符串是否全大写
}
// 调用函数:不用写外部名,直接传值
let string = "HELLO, WORLD"
let isAllUpper = isUppercase(string) // 无需写 isUppercase(_: string)
print("是否全大写:\(isAllUpper)") // 输出 true
- 适用场景:参数含义非常明确(比如判断字符串、添加元素),省略外部名能让调用更简洁。
六、实战练习:封装 “多面骰子掷多次” 的函数
结合今天的知识点,封装一个 “掷指定面数的骰子 N 次,返回所有点数” 的函数:
// 函数功能:掷 Sides 面的骰子 Count 次,返回点数数组
func rollDices(sides: Int, count: Int) -> [Int] {
var rolls = [Int]() // 存储所有点数的数组
for _ in 1...count {
let roll = Int.random(in: 1...sides) // 每次掷骰子的点数
rolls.append(roll)
}
return rolls // 返回点数数组
}
// 调用函数:掷 6 面骰子 4 次
let diceRolls = rollDices(sides: 6, count: 4)
print("4次掷骰子结果:\(diceRolls)") // 输出类似 [3, 6, 2, 5]
- 思路拆解:用
sides和count作为参数(定制骰子面数和次数),内部用循环生成随机数,最后返回点数数组 —— 这就是函数 “封装逻辑” 的核心:把复杂操作藏在函数里,外部只需传参数、拿结果。
七、Day7 学习总结:函数核心知识点
| 函数类型 | 关键语法 | 适用场景 |
|---|---|---|
| 无参数无返回值 | func 名() { 体 } |
执行固定操作(如打印欢迎语) |
| 带参数(单个 / 多个) | func 名(参1: 型1, 参2: 型2) { 体 } |
需定制化操作(如打印不同乘法表) |
| 带返回值(单个) | func 名() -> 型 { return 结果 } |
需输出处理结果(如掷骰子、判断字符串) |
| 返回多值(元组) | func 名() -> (键1: 型1, 键2: 型2) { 体 } |
需返回多个相关值(如用户姓名、坐标) |
| 自定义外部参数名 | func 名(外参 内参: 型) { 体 } |
优化调用可读性(如 for: 5) |
| 忽略外部参数名 | func 名(_ 内参: 型) { 体 } |
参数含义明确(如判断字符串是否全大写) |
明日计划
Day8 要学 Swift 的 “函数进阶”—— 包括默认参数、可变参数,还有函数的 “嵌套调用”,把今天的基础函数变得更强大。有一起打卡的朋友吗?评论区可以分享你封装的小函数(比如 “计算两个数的加减乘除”“统计数组中的偶数个数”)~
更多推荐


所有评论(0)