Day7 正式进入 Swift “代码复用核心区”—— 函数。函数能把重复的代码片段封装成一个 “工具”,不仅能减少重复编写,还能让代码更模块化(比如把 “掷骰子”“判断字符串字母是否相同” 做成函数,后续直接调用)。今天学了函数的定义、参数配置、返回值(包括多值返回的元组),还有外部参数名的实用技巧,整理了实操代码和场景对比,新手朋友跟着练能快速掌握 “代码封装” 的思路~

目录

一、函数基础:把代码片段封装成 “可调用工具”

1. 无参数、无返回值函数

二、带参数的函数:让函数更灵活(可定制化)

1. 单个参数函数

2. 多个参数函数

三、带返回值的函数:让函数 “输出结果”

1. 基础返回值(单个值)

2. 简化写法:单句函数可省略 return

四、返回多值:用元组解决 “返回多个结果” 的需求

1. 用元组返回多值

2. 元组的其他用法

五、函数参数的进阶:外部参数名(优化调用体验)

1. 自定义外部参数名

2. 忽略外部参数名(用 _)

六、实战练习:封装 “多面骰子掷多次” 的函数

七、Day7 学习总结:函数核心知识点

明日计划


一、函数基础:把代码片段封装成 “可调用工具”

函数的核心是 “输入(参数)→ 处理 → 输出(返回值)”,先从最简单的 “无参数、无返回值” 函数入手,理解基本结构。

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 的 “函数进阶”—— 包括默认参数、可变参数,还有函数的 “嵌套调用”,把今天的基础函数变得更强大。有一起打卡的朋友吗?评论区可以分享你封装的小函数(比如 “计算两个数的加减乘除”“统计数组中的偶数个数”)~

更多推荐