news 2026/9/4 8:34:06

Swift 结构体:从基础到进阶的全面指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Swift 结构体:从基础到进阶的全面指南

1. 引言

在 Swift 中,结构体(Struct)是构建代码模块的核心类型之一。与类(Class)不同,结构体是值类型,这一特性让它在 Swift 开发中扮演着极其重要的角色。无论是定义一个坐标点、一个网络请求的响应模型,还是业务中的领域对象,结构体都无处不在。本文将从基础语法出发,结合丰富的代码实例,带你全面掌握 Swift 结构体的定义、使用、进阶特性以及它与类的区别。

2. 结构体的基本定义与实例化

结构体通过struct关键字定义。一个最简单的结构体可以只包含存储属性,Swift 会自动为结构体生成一个「成员逐一构造器」(Memberwise Initializer),方便我们直接创建实例。

// 定义一个表示坐标点的结构体 struct Point { var x: Double var y: Double } // 使用自动生成的成员逐一构造器创建实例 let origin = Point(x: 0.0, y: 0.0) var target = Point(x: 10.5, y: 20.0) print("原点坐标:\(origin.x), \(origin.y)") print("目标坐标:\(target.x), \(target.y)") // 修改结构体实例的属性(需要 var 声明) target.x = 15.0 print("更新后的目标坐标:\(target.x), \(target.y)")

在上面的例子中,我们没有编写任何初始化方法,但 Swift 自动提供了Point(x:y:)构造器。需要注意的是,如果结构体的属性使用let声明,则该属性在实例创建后不可修改。

3. 存储属性与计算属性

结构体可以同时拥有存储属性(Stored Properties)和计算属性(Computed Properties)。计算属性不直接存储值,而是通过计算得到,常用于派生数据。

// 定义一个表示矩形的结构体 struct Rectangle { var width: Double var height: Double // 计算属性:面积 var area: Double { return width * height } // 计算属性:周长 var perimeter: Double { return 2 * (width + height) } // 只读计算属性可以省略 get 关键字 var isSquare: Bool { return width == height } } let rect = Rectangle(width: 5.0, height: 3.0) print("面积:\(rect.area)") print("周长:\(rect.perimeter)") print("是否为正方形:\(rect.isSquare)") let square = Rectangle(width: 4.0, height: 4.0) print("正方形面积:\(square.area),是否为正方形:\(square.isSquare)")

计算属性每次访问时都会重新计算,因此它不能用于频繁读取且计算开销较大的场景。如果计算开销大,可以考虑使用存储属性加自定义方法,或者使用lazy关键字。

4. 方法(Methods)

结构体可以定义实例方法和类型方法。实例方法操作实例自身的属性,而类型方法(使用static关键字)则与具体实例无关。

// 定义一个表示温度的结构体 struct Temperature { var celsius: Double // 实例方法:转换为华氏温度 func toFahrenheit() -> Double { return celsius * 9 / 5 + 32 } // 实例方法:转换为开尔文温度 func toKelvin() -> Double { return celsius + 273.15 } // 类型方法:从华氏温度创建实例 static func fromFahrenheit(_ fahrenheit: Double) -> Temperature { return Temperature(celsius: (fahrenheit - 32) * 5 / 9) } // 类型方法:从开尔文温度创建实例 static func fromKelvin(_ kelvin: Double) -> Temperature { return Temperature(celsius: kelvin - 273.15) } } let bodyTemp = Temperature(celsius: 36.5) print("体温华氏度:\(bodyTemp.toFahrenheit())") print("体温开尔文:\(bodyTemp.toKelvin())") let boilingPoint = Temperature.fromFahrenheit(212) print("水的沸点(摄氏):\(boilingPoint.celsius)")

类型方法非常适合作为「工厂方法」,用来提供多种创建实例的入口,让调用方的语义更加清晰。

5. 值类型与引用类型的区别

结构体是值类型(Value Type),而类是引用类型(Reference Type)。这是 Swift 中最重要的概念之一。值类型在赋值或传递时会被复制,而引用类型则共享同一份实例。

// 结构体:值类型 struct Position { var x: Int var y: Int } var posA = Position(x: 1, y: 2) var posB = posA // 这里会复制一份独立的副本 posB.x = 100 print("posA.x = \(posA.x)") // 输出 1,posA 不受影响 print("posB.x = \(posB.x)") // 输出 100 // 类:引用类型 class Car { var speed: Int = 0 } let carA = Car() let carB = carA // 这里共享同一个实例 carB.speed = 120 print("carA.speed = \(carA.speed)") // 输出 120,carA 和 carB 指向同一对象 print("carB.speed = \(carB.speed)") // 输出 120

理解值类型与引用类型的区别,有助于避免在开发中遇到「意外修改」的问题。当你希望数据被独立复制、互不影响时,优先使用结构体;当你需要共享状态、使用继承时,则选择类。

6. 结构体中的 mutating 方法

默认情况下,结构体的实例方法不能修改自身的属性。如果需要在方法中修改属性,必须将方法标记为mutating。这是因为结构体是值类型,修改属性实际上是在修改实例本身。

// 定义一个计数器结构体 struct Counter { var count = 0 // mutating 方法:增加计数 mutating func increment() { count += 1 } // mutating 方法:重置计数 mutating func reset() { count = 0 } // mutating 方法:按指定步长增加 mutating func increment(by amount: Int) { count += amount } } var counter = Counter() counter.increment() counter.increment(by: 5) print("当前计数:\(counter.count)") // 输出 6 counter.reset() print("重置后计数:\(counter.count)") // 输出 0

注意:只有使用var声明的结构体实例才能调用mutating方法。如果使用let声明实例,则无法调用任何mutating方法。

7. 自定义构造器(Initializers)

除了自动生成的成员逐一构造器,我们还可以为结构体自定义构造器,以便在初始化时执行额外的逻辑或提供默认值。

// 定义一个表示用户的结构体 struct User { var name: String var age: Int var email: String // 自定义构造器:带默认邮箱 init(name: String, age: Int) { self.name = name self.age = age self.email = "\(name.lowercased())@example.com" } // 自定义构造器:完整参数 init(name: String, age: Int, email: String) { self.name = name self.age = age self.email = email } // 自定义构造器:带年龄默认值 init(name: String) { self.name = name self.age = 0 self.email = "\(name.lowercased())@example.com" } } let user1 = User(name: "Alice", age: 25) print("用户1:\(user1.name), \(user1.age), \(user1.email)") let user2 = User(name: "Bob", age: 30, email: "bob@company.com") print("用户2:\(user2.name), \(user2.age), \(user2.email)") let user3 = User(name: "Charlie") print("用户3:\(user3.name), \(user3.age), \(user3.email)")

一旦自定义了构造器,Swift 就不会再自动生成成员逐一构造器。如果仍然需要它,可以在扩展(Extension)中显式保留。

8. 扩展(Extension)与协议(Protocol)

结构体可以通过扩展来增加功能,也可以遵循协议(Protocol)来满足特定的接口要求。这使得结构体在保持轻量的同时,具备强大的扩展能力。

// 定义一个基础结构体 struct Book { var title: String var author: String var pages: Int } // 通过扩展添加计算属性和方法 extension Book { var description: String { return "《\(title)》作者:\(author),共 \(pages) 页" } func isLongBook() -> Bool { return pages > 300 } } // 定义一个协议 protocol Summarizable { func summary() -> String } // 让结构体遵循协议 extension Book: Summarizable { func summary() -> String { return "\(title) - \(author)" } } let book = Book(title: "Swift 编程实战", author: "张三", pages: 420) print(book.description) print("是否长篇小说:\(book.isLongBook())") print("摘要:\(book.summary())")

通过扩展遵循协议,可以让结构体的职责更加清晰,也便于代码的模块化组织。

9. 结构体与类的选择建议

在 Swift 开发中,Apple 官方推荐优先使用结构体。以下是一些选择建议:

  • 优先使用结构体:当数据量较小、不需要继承、且希望值语义时,优先选择结构体。
  • 使用类:当需要继承、需要引用语义(共享状态)、或者需要与 Objective-C 互操作时,选择类。
  • 结合使用:在实际项目中,常常用结构体定义数据模型,用类管理生命周期和共享状态。
// 实际项目中的常见组合用法 struct Product { let id: Int let name: String var price: Double } class ShoppingCart { var items: [Product] = [] func add(_ product: Product) { items.append(product) } var totalPrice: Double { return items.reduce(0) { $0 + $1.price } } } let phone = Product(id: 1, name: "智能手机", price: 5999.0) let case_ = Product(id: 2, name: "手机壳", price: 99.0) let cart = ShoppingCart() cart.add(phone) cart.add(case_) print("购物车总价:\(cart.totalPrice) 元")

在这个例子中,Product使用结构体表示不可变的数据模型,ShoppingCart使用类来管理可变的购物车状态,两者各司其职。

10. 总结

Swift 结构体是值类型的代表,具有定义简洁、自动构造器、计算属性、方法、扩展和协议遵循等丰富特性。理解结构体的值语义以及与类的区别,是写出健壮 Swift 代码的关键。在实际开发中,建议优先使用结构体来定义数据模型,仅在确实需要引用语义或继承时使用类。希望本文的代码实例能帮助你更好地掌握 Swift 结构体的使用。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/4 9:02:22

高校学工管理系统白皮书:从业务痛点到落地路径

✅作者简介:合肥自友科技 📌核心产品:智慧校园平台(包括教工管理、学工管理、教务管理、考务管理、后勤管理、德育管理、资产管理、公寓管理、实习管理、就业管理、离校管理、科研平台、档案管理、学生平台等26个子平台) 。公司所有人员均有多…

作者头像 李华
网站建设 2026/9/4 14:50:58

YOLO 工业管道缺陷检测实战|2614 张 4 类 VOC/YOLO 不平衡数据集、微小裂纹涨点、管网巡检落地全流程工程

目录 一、前言 二、2614 张管道破损泄漏 4 类数据集完整解析 2.1 数据集基础完整参数 2.2 工业管道数据集专属优势 2.3 数据集固有短板与配套涨点方案 三、微小裂纹不平衡样本 YOLO 涨点核心原理 四、三大管网智能巡检落地应用案例 案例 1 市政供水管网无人机全域巡检项…

作者头像 李华
网站建设 2026/9/4 9:13:15

【关注可白嫖源码】--课程设计+毕业设计+24403基于SpringBoot的主题音乐播放与推荐系统[编号:project24403](案例分析)

本文仅展示核心实现逻辑与部分代码片段,完整项目源码、配套文档、数据库脚本内容较多,篇幅有限无法全部放出。有需要完整资源的同学,可以在评论区留言【资料或领源码】,我会一一回复站内私信,发送完整文件第一章 绪论1…

作者头像 李华
网站建设 2026/9/4 8:10:07

【关注可白嫖源码】--课程设计+毕业设计+基于Spring boot的社区旧物回收管理系统的设计与实现[编号:project25381](案例分析)

本文仅展示核心实现逻辑与部分代码片段,完整项目源码、配套文档、数据库脚本内容较多,篇幅有限无法全部放出。有需要完整资源的同学,可以在评论区留言【资料或领源码】,我会一一回复站内私信,发送完整文件第一章 绪论1…

作者头像 李华
网站建设 2026/9/4 1:37:15

基于AUTOSAR与MBD的车身后域控制器开发实战:S32K344平台三合一集成

简介:本资源为面向大学生方程式赛车(Formula Student)团队的车规级后车身域控制器完整开发套件,聚焦智能配电、低压电池监测与TBOX远程通信三大核心功能,解决赛事车辆电子系统高可靠性、功能集成与实时数据回传等工程痛…

作者头像 李华
网站建设 2026/9/4 8:11:10

JWT登录+Vuex状态管理+验证码解锁:SPA项目认证实战

做八股文网站这类项目时,总绕不开一个核心模块:登录认证。我在自己折腾“面试刷题站”的过程中,把验证码解锁、JWT登录、Vuex状态管理这一整套流程从零撸了一遍,踩了不少坑,也把底层原理摸透了。这篇就把完整的技术方案…

作者头像 李华