2.1 台词与动作:函数参数与函数类型


2.1 台词与动作:函数参数与函数类型

本节摘要:本节把排片界面的逻辑装进函数——从定义与调用、参数标签、默认值、可变参数,讲到函数类型与嵌套函数。核心结论:函数在 Swift 里是"一等公民",能被赋值、传参、返回,这个性质是下一节闭包的地基,也是第5章 async 函数的前置。

序幕备好了道具,第一幕开演,界面的每个动作都要有台词本——函数就是台词本。

开演铃响:台词本的第一页

排片界面出生后干的第一件事是"组装界面文案"。先用最朴素的函数把它写出来:

// 定义:func 关键字 + 名字 + 参数表 + 返回类型 func seatLine(hall: String, seats: Int) -> String { return "\(hall) 余 \(seats) 座" } // 调用:参数名在调用处必须写出 let line = seatLine(hall: "IMAX 厅", seats: 12) print(line) // 输出:IMAX 厅 余 12 座

参数名 hall: 在调用处必须写——这叫参数标签,它是 Swift 的阅读性设计:调用处读起来像一句自然话。不想要它,用下划线抹掉:

func seatLine(_ hall: String, seats: Int) -> String { "\(hall) 余 \(seats) 座" // 单表达式可省略 return } print(seatLine("3 号厅", seats: 8)) // 输出:3 号厅 余 8 座

内外名字可以不同:func load(from url描述: String) 这种写法让定义处用短名、调用处用长名,界面层代码尤其受益。

三种常用参数形态

台词本越写越厚,参数形态也要跟上排片业务的真需求。

// 形态一:默认值——多数调用不用传 func greet(name: String, isVip: Bool = false) -> String { isVip ? "尊贵的 \(name),已为您锁定黄金位" : "\(name),欢迎光临" } print(greet(name: "老周")) // 输出:老周,欢迎光临 print(greet(name: "老周", isVip: true)) // 输出:尊贵的 老周,已为您锁定黄金位 // 形态二:可变参数——场次时间不固定几个 func buildShowtime(title: String, hours: Int...) -> String { let times = hours.map { "\($0):00" }.joined(separator: " / ") return "《\(title)》\(times)" } print(buildShowtime(title: "雾中灯塔", hours: 10, 14, 19, 22)) // 输出:《雾中灯塔》10:00 / 14:00 / 19:00 / 22:00 // 形态三:inout——把修改带出函数(少用,但要认识) func resetSeats(_ counter: inout Int) { counter = 0 } var seats = 42 resetSeats(&seats) print(seats) // 输出:0

我的取舍建议:默认值放心用;可变参数在"凑一串同类型值"时用;inout 能不用就不用——它破坏"函数只通过返回值影响外界"的纯净性,界面上状态的修改走第7章的数据流更稳。

函数类型:台词也能当道具传

这是本节真正的主菜。(String, Int) -> String 本身就是一个类型,描述"吃一个字符串一个整数、吐一个字符串"的所有函数。函数可以赋给常量、存进数组、当参数传、当返回值还:

// 声明一个函数类型常量,把函数当值存 let formatter: (String, Int) -> String = seatLine print(formatter("情侣厅", 6)) // 输出:情侣厅 余 6 座 // 当参数传:不同的计价策略 func price(base: Double, using strategy: (Double) -> Double) -> Double { strategy(base) } let vipPrice: (Double) -> Double = { $0 * 0.8 } // 闭包初见,下一节主角 let weekendPrice: (Double) -> Double = { $0 * 1.2 } print(price(base: 60, using: vipPrice)) // 输出:48.0 print(price(base: 60, using: weekendPrice)) // 输出:72.0 // 当返回值还:根据时段挑一个计价函数 func strategy(forHour hour: Int) -> (Double) -> Double { hour >= 18 ? { $0 * 1.2 } : { $0 * 0.9 } } print(price(base: 60, using: strategy(forHour: 20))) // 输出:72.0(晚场上浮)

注意 vipPrice 的类型标注 (Double) -> Double——函数类型标注同时约束了花括号里必须是什么形状。这种"值即是函数"的写法,在排序、动画、计价这类"策略会换"的场景里是标准武器。

嵌套函数:把助理藏在主演身后

台词本里还可以有更小的台词本。嵌套函数适合"只有外层会用"的辅助逻辑,避免它泄漏到文件作用域:

// 外层:把一晚场次格式化成界面文案 func nightBoard(films: [(String, Int)]) -> String { // 嵌套函数 1:单部影片转一行 func row(_ film: (String, Int)) -> String { "《\(film.0)》\(film.1) 分钟" } // 嵌套函数 2:拼分隔线 func divider(of count: Int) -> String { String(repeating: "—", count: count) } var lines = films.map(row) lines.insert(divider(of: 12), at: 0) lines.append(divider(of: 12)) return lines.joined(separator: "\n") } print(nightBoard(films: [("雾中灯塔", 118), ("星际列车", 142)])) // 输出: // ———————————— // 《雾中灯塔》118 分钟 // 《星际列车》142 分钟 // ————————————

嵌套函数能直接读外层函数的常量(比如 divider 若要用外层的宽度变量,无需传参),这是第2.2 节"捕获"机制的预演。

⚠️ 常见坑:把所有辅助函数平铺在文件顶层。一个文件几十个顶层函数,谁跟谁配套全靠命名猜。内聚的辅助逻辑收进嵌套函数或类型内部(第3章),文件的可读性立刻回来。

💡 关键直觉:函数类型是 Swift 分派"行为"的通用货币。看到 using:handler:completion: 这类参数名,脑子里就该浮现"这里要传一段行为",而不是"这里要传一个数"。

台词本的收束点

  • 参数标签让调用处读起来像自然语言,内外名可分离;
  • 默认值减少调用方负担,可变参数收纳同类型的一串;
  • inout 罕用,界面状态修改有更好的通道(第7章);
  • 函数是一等公民:可赋值、传参、返回,函数类型就是它的身份证;
  • 嵌套函数收编内聚的辅助逻辑,并预演了捕获语义。

台词本能定义"立刻执行的动作"了,但界面还需要"以后才执行的动作"——刷新完成后的回调、动画结束后的清理。这些便条由 2.2 节的替补演员闭包来递。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U