Swift 常量详解:let 与 const 的正确使用方式

发布时间:2026/10/24 7:33:42

Swift 常量详解:let 与 const 的正确使用方式 1. 引言在 Swift 编程语言中常量是构建安全、可预测代码的基础。与变量不同常量一旦赋值便不可更改这不仅能防止意外修改还能让代码的意图更加清晰。本文将深入讲解 Swift 常量的定义、使用场景以及最佳实践并通过丰富的代码实例帮助你快速掌握。2. 什么是常量常量是指在程序运行过程中值保持不变的量。Swift 使用let关键字来声明常量。一旦为常量赋值就不能再修改它的值。这种不可变性是 Swift 类型安全体系的重要组成部分。与变量使用var声明相比常量具有以下优势安全性防止代码在无意中修改重要数据。可读性明确告诉阅读者该值不会变化降低理解成本。性能优化编译器可以对常量进行更多优化提升运行效率。3. 常量的基本用法使用let关键字声明常量语法非常简单let constantName: Type value其中类型标注: Type是可选的Swift 支持类型推断。下面是一些基本示例// 声明一个整数常量 let maxAttempts 5 // 声明一个字符串常量 let appName MySwiftApp // 声明一个浮点常量 let pi 3.14159 // 显式指定类型 let isEnabled: Bool true // 打印常量值 print(应用名称\(appName)) print(最大尝试次数\(maxAttempts))4. 常量的类型推断Swift 强大的类型推断机制允许你在声明常量时省略类型标注。编译器会根据赋值的字面量自动推断常量的类型// 整数类型推断为 Int let age 25 // 浮点数类型推断为 Double let height 1.75 // 字符串类型推断为 String let city 北京 // 布尔类型推断为 Bool let isLoggedIn true // 使用 type(of:) 查看推断出的类型 print(type(of: age)) // 输出Int print(type(of: height)) // 输出Double print(type(of: city)) // 输出String print(type(of: isLoggedIn)) // 输出Bool5. 常量的不可变性常量的核心特性是不可变性。一旦赋值任何试图修改常量的操作都会导致编译错误。下面通过代码演示let fixedValue 100 // 下面的代码会报错Cannot assign to value: fixedValue is a let constant // fixedValue 200 // 正确的做法如果需要可变值使用 var var mutableValue 100 mutableValue 200 print(可变值\(mutableValue))编译器会在编译阶段就拦截对常量的修改这有助于在开发早期发现潜在问题。6. 常量与变量的选择在 Swift 开发中一个重要的原则是优先使用常量只有在值确实需要变化时才使用变量。下面通过对比示例来说明// 不推荐使用变量声明不会变化的值 var userName Alice var maxRetryCount 3 // 推荐使用常量声明不会变化的值 let userName Alice let maxRetryCount 3 // 需要变化的值才使用变量 var currentScore 0 currentScore 10 print(当前得分\(currentScore))遵循这一原则可以让代码更加健壮减少因意外赋值导致的 bug。7. 常量的作用域常量可以定义在全局作用域、函数作用域或类/结构体内部。不同作用域的常量具有不同的生命周期和访问范围// 全局常量 let globalConstant 全局常量 func demoScope() { // 函数内局部常量 let localConstant 局部常量 print(localConstant) print(globalConstant) // 可以访问全局常量 } class MyClass { // 类型属性类常量 static let classConstant 类常量 // 实例属性实例常量 let instanceConstant: String init(value: String) { self.instanceConstant value } } demoScope() print(MyClass.classConstant) let obj MyClass(value: 实例常量) print(obj.instanceConstant)8. 常量与集合类型当常量是数组、字典或集合时需要注意常量本身不可重新赋值但其内部元素是否可变取决于集合的类型。Swift 中的Array、Dictionary和Set是值类型因此用let声明的集合其元素也不可修改// 常量数组元素不可修改 let fruits [苹果, 香蕉, 橙子] // fruits.append(葡萄) // 错误Cannot use mutating member on immutable value // fruits[0] 西瓜 // 错误Cannot assign through subscript // 常量字典键值对不可修改 let scores [数学: 95, 语文: 88] // scores[英语] 90 // 错误 // 常量集合 let uniqueNumbers: SetInt [1, 2, 3] // uniqueNumbers.insert(4) // 错误 // 如果需要可变集合使用 var var mutableFruits [苹果, 香蕉] mutableFruits.append(葡萄) print(mutableFruits)9. 常量与引用类型当常量指向的是引用类型如类实例时常量本身不可重新赋值但通过该常量可以修改对象的属性或调用修改方法。这是因为引用类型是共享的class Counter { var count 0 } // 常量指向类实例 let counter Counter() counter.count 10 // 允许修改对象的属性 print(计数\(counter.count)) // counter Counter() // 错误Cannot assign to value: counter is a let constant // 对比结构体是值类型let 声明的结构体属性不可修改 struct Point { var x: Int var y: Int } let point Point(x: 1, y: 2) // point.x 5 // 错误Cannot assign to property: point is a let constant10. 常量与可选类型常量同样可以声明为可选类型。可选常量在赋值前默认为nil赋值后不可再修改// 声明可选常量 let optionalValue: Int? nil // optionalValue 10 // 错误Cannot assign to value: optionalValue is a let constant // 在初始化时直接赋值 let initializedOptional: String? Hello print(initializedOptional ?? 默认值) // 可选常量配合 if let 使用 let username: String? SwiftUser if let name username { print(用户名\(name)) } else { print(用户名为空) }11. 常量与元组元组可以将多个值组合成一个复合值。使用let声明的元组其元素同样不可修改// 声明元组常量 let coordinates (x: 10, y: 20) print(x: \(coordinates.x), y: \(coordinates.y)) // 元组解构 let (width, height) (1920, 1080) print(分辨率\(width) x \(height)) // 元组作为函数返回值 func getMinMax() - (min: Int, max: Int) { return (1, 100) } let result getMinMax() print(最小值\(result.min)最大值\(result.max)) // 修改元组元素会报错 // coordinates.x 30 // 错误Cannot assign to property: coordinates is a let constant12. 常量与计算属性虽然常量本身不可变但你可以使用计算属性来动态获取值。计算属性不存储值而是每次访问时计算struct Circle { let radius: Double // 计算属性每次访问时计算 var area: Double { return Double.pi * radius * radius } var circumference: Double { return 2 * Double.pi * radius } } let circle Circle(radius: 5.0) print(面积\(circle.area)) print(周长\(circle.circumference)) // 计算属性是只读的不能赋值 // circle.area 100 // 错误Cannot assign to property: area is a get-only property13. 常量与函数参数在 Swift 中函数参数默认是常量。这意味着在函数体内不能修改参数的值func greet(name: String) { // name 是常量不能修改 // name 新名字 // 错误Cannot assign to value: name is a let constant print(你好\(name)) } // 如果需要修改参数使用 inout 参数 func increment(_ number: inout Int) { number 1 } var count 10 increment(count) print(递增后\(count)) // 调用函数 greet(name: Swift)14. 常量与闭包闭包可以捕获常量。被捕获的常量在闭包内保持其值即使闭包在常量作用域之外被调用func makeIncrementer(amount: Int) - () - Int { var total 0 // 捕获 amount 常量 return { total amount return total } } let incrementByTen makeIncrementer(amount: 10) print(incrementByTen()) // 输出10 print(incrementByTen()) // 输出20 print(incrementByTen()) // 输出30 // 常量捕获示例 let baseValue 100 let addBase: (Int) - Int { value in return value baseValue } print(addBase(50)) // 输出15015. 常量与枚举枚举的关联值和原始值经常与常量配合使用。枚举本身是值类型用let声明的枚举常量不可修改enum Direction { case north, south, east, west } enum StatusCode: Int { case success 200 case notFound 404 case serverError 500 } // 枚举常量 let direction Direction.north let status StatusCode.success // 使用 switch 匹配枚举 switch direction { case .north: print(向北) case .south: print(向南) case .east: print(向东) case .west: print(向西) } // 枚举原始值 print(状态码\(status.rawValue)) // 枚举关联值 enum Barcode { case upc(Int, Int, Int, Int) case qrCode(String) } let productBarcode Barcode.upc(8, 85909, 51226, 3) switch productBarcode { case .upc(let numberSystem, let manufacturer, let product, let check): print(UPC: \(numberSystem)-\(manufacturer)-\(product)-\(check)) case .qrCode(let code): print(QR code: \(code)) }16. 常量与泛型在泛型编程中常量同样扮演重要角色。泛型函数或类型中的常量可以保持类型安全// 泛型函数中的常量 func findMaxT: Comparable(in array: [T]) - T? { guard let first array.first else { return nil } var maxValue first for item in array { if item maxValue { maxValue item } } return maxValue } let numbers [3, 7, 1, 9, 5] if let maxNumber findMax(in: numbers) { print(最大值\(maxNumber)) } let strings [apple, banana, cherry] if let maxString findMax(in: strings) { print(最大字符串\(maxString)) } // 泛型结构体中的常量 struct StackElement { private var items: [Element] [] mutating func push(_ item: Element) { items.append(item) } mutating func pop() - Element? { return items.popLast() } var count: Int { return items.count } } var stack StackInt() stack.push(1) stack.push(2) stack.push(3) print(栈元素个数\(stack.count)) print(弹出\(stack.pop() ?? -1))17. 常量与协议协议中可以使用常量要求但通常通过计算属性或静态属性来实现。下面展示如何在协议中使用常量protocol Vehicle { var maxSpeed: Int { get } var name: String { get } } struct Car: Vehicle { // 使用常量满足协议要求 let maxSpeed: Int let name: String } struct Bicycle: Vehicle { let maxSpeed: Int let name: String } let car Car(maxSpeed: 200, name: 跑车) let bicycle Bicycle(maxSpeed: 30, name: 自行车) func describe(vehicle: Vehicle) { print(\(vehicle.name) 的最高速度是 \(vehicle.maxSpeed) km/h) } describe(vehicle: car) describe(vehicle: bicycle) // 协议中的静态常量 protocol AppConfig { static var appName: String { get } static var version: String { get } } struct DevelopmentConfig: AppConfig { static let appName DevApp static let version 1.0.0-beta } struct ProductionConfig: AppConfig { static let appName ProductionApp static let version 1.0.0 } print(开发环境\(DevelopmentConfig.appName) \(DevelopmentConfig.version)) print(生产环境\(ProductionConfig.appName) \(ProductionConfig.version))18. 常量与错误处理在错误处理中常量常用于定义错误码和错误信息确保错误处理的稳定性和可读性// 定义错误类型 enum NetworkError: Error { case badURL case timeout case serverError(code: Int) } // 使用常量定义错误信息 let errorMessages: [NetworkError: String] [ .badURL: 无效的 URL, .timeout: 请求超时, .serverError(code: 500): 服务器内部错误 ] func fetchData(from urlString: String) throws - String { // 使用常量校验 URL let validURLPrefix https:// guard urlString.hasPrefix(validURLPrefix) else { throw NetworkError.badURL } // 模拟网络请求 let simulatedResponse 模拟数据 return simulatedResponse } // 错误处理示例 do { let data try fetchData(from: https://example.com) print(获取数据\(data)) } catch NetworkError.badURL { print(错误无效的 URL) } catch NetworkError.timeout { print(错误请求超时) } catch { print(未知错误\(error)) }19. 常量与并发编程在 Swift 并发编程中常量对于保证线程安全尤为重要。不可变数据天然适合在多线程环境中共享import Foundation // 使用常量定义线程安全的配置 let threadSafeConfig [ timeout: 30, maxRetries: 3, enableLogging: true ] // 使用 DispatchQueue 模拟并发访问 let queue DispatchQueue(label: com.example.concurrent, attributes: .concurrent) for index in 0..5 { queue.async { // 并发读取常量是安全的
延伸阅读

更多相关文章

2026/10/24 7:33:42

坚果云收件箱的10个神用法:从收集周报到客户合同文件自动归档

文章目录一、文件收集的「三大灾难」二、收件箱的核心机制2.1 收件箱 vs 传统收集方式2.2 收件箱的创建步骤三、10个神用法逐一拆解用法一:团队周报收集用法二:学生作业提交用法三:客户合同签约用法四:供应商报价收集用法五&#…

2026/10/24 7:33:42

SSD1322 OLED驱动芯片底层机制拆解:从接口时序到灰度表

简介:SSD1322数据手册是Solomon Systech公司发布的高性能有机发光二极管驱动控制器官方技术文档,面向显示驱动开发工程师、嵌入式硬件设计人员和屏体调试工程师,用于解决芯片选型、引脚连接、寄存器配置以及显示时序匹配等问题。资源以单个PD…

2026/10/24 7:33:42

响应式数据流实战:从零构建实时数据处理内核

1. 从“rea”这个标题说起:一个被低估的缩写背后藏着什么第一次看到“rea”这个标题,我承认自己愣了几秒。它太短了,短到像是一个被截断的单词,又像是一个随手敲下的代号。但恰恰是这种极简的标题,往往藏着最值得深挖的…

2026/10/24 8:23:45

大模型排行榜-Arena-Agent-榜单解读

Agent 排行榜到底怎么看:2.1 亿次真实会话拆出的 5 个维度,前六名其实分不出胜负数据截至 2026 年 10 月 11 日。Agent 行为数据取自 Arena AI 公开排行榜(arena.ai/leaderboard/agent),能力分取自 Artificial Analysi…

2026/10/24 8:23:45

从 RSSI 到楼层:蓝牙信标室内定位的部署、算法与工程实践

从 RSSI 到楼层:蓝牙信标室内定位的部署、算法与工程实践 一、开篇:户外的米级,室内的盲区 卫星定位给户外人员管理立下了米级基准,但人一进楼宇、车间、地库,墙体、钢结构和顶棚层层衰减卫星信号,位置就“…

2026/10/24 8:23:45

2026算力网络选型指南:6大评估维度+12家主流服务商横向拆解

2026年做算力网络选型,难点不在服务商数量,而在把“算力能否连、业务能否稳、成本能否控”拆成可验证的条件。工信部在2025中国算力大会披露(2025年8月),截至2025年6月底,全国智能算力规模达到788 EFLOPS&a…

2026/10/24 8:18:45

MATLAB相关性分析建模:从皮尔逊到偏相关与滚动诊断

简介:本资源是一套面向数学建模初学者与MATLAB入门者的相关性分析实战教学包,聚焦变量间关联性度量这一建模关键环节,适用于课程设计、竞赛备赛及科研数据预处理场景。压缩包共11个文件(194KB),含3个Excel体…

2026/10/23 22:56:35

金融AI落地指南:从调研报告到技术选型与工程实践

简介:这份PDF报告聚焦2025年金融服务业中国AI现状与趋势,面向金融科技从业者、AI战略规划人员及关注行业数字化转型的研究者,帮助读者把握生成式AI在银行、支付、交易等场景中的落地路径与投资方向。资源包内含1个PDF文件,大小约1…

2026/10/24 0:02:40

MATLAB缩进快捷键与批量格式化实战指南

1. 被自动缩进折磨的那些年如果你写过MATLAB代码,大概率经历过这种场景:从某个文档、网页或者聊天记录里复制了一段代码,粘贴进编辑器之后,每一行前面都带着莫名其妙的空格,有的行首是四个空格,有的是一个T…

2026/10/24 0:02:40

用Poco实现Qt风格信号与槽的跨平台C++方案

简介:本资源是一份面向C中级开发者的技术实践工程,聚焦于在非Qt框架环境下模拟实现Qt核心通信机制——信号与槽,借助Poco网络库的事件系统完成解耦式对象通信。适用于需在跨平台C项目中引入松耦合回调机制、但受限于无法集成Qt依赖的开发场景…

2026/10/24 0:02:40

ESXi裸机虚拟化安装指南:从硬件兼容到虚拟机部署

1. 为什么还要折腾ESXi:从一台闲置机器说起手里攒了几台淘汰下来的迷你主机,配置不算差,i5加16G内存,扔了可惜,装个桌面系统又觉得浪费。这种场景下,ESXi就成了一个绕不开的选择。它是一套裸机虚拟化平台&a…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑