【Swift】Swift基础语法:函数、闭包、枚举、结构体、类与属性

一、Swift基础语法

1.6 函数(Function)

函数是代码复用的核心,Swift 支持多种函数特性(外部参数、可变参数、输入输出参数等)。

1. 函数基本定义

  • 语法:func 函数名(参数列表) -> 返回类型 { 函数体 },无返回值时返回类型可省略或写 Void
Swift 复制代码
// 1. 有返回值函数(返回 String)
func runoob(site: String) -> String {
    return site
}
print(runoob(site: "www.bytedance.com")) // 输出:www.bytedance.com

// 2. 多参数函数
func runoob(name: String, site: String) -> String {
    return name + ":" + site
}
print(runoob(name: "字节跳动", site: "www.bytedance.com")) // 输出:字节跳动:www.bytedance.com

// 3. 无返回值函数(省略 -> Void)
func siteName() {
    print("www.bytedance.com")
}
siteName() // 输出:www.bytedance.com

// 4. 返回元组(支持多返回值)
func minMax(array: [Int]) -> (min: Int, max: Int)? { // 返回可选元组(处理空数组)
    if array.isEmpty { return nil }
    var currentMin = array[0], currentMax = array[0]
    for value in array[1..<array.count] {
        if value < currentMin { currentMin = value }
        else if value > currentMax { currentMax = value }
    }
    return (currentMin, currentMax)
}

// 调用返回元组的函数(用可选绑定解析)
let boundArray: [Int] = [3, 54, 21, 214, 6, 0]
if let minMaxValue = minMax(array: boundArray) {
    print("minValue = \(minMaxValue.min) maxValue = \(minMaxValue.max)") // 输出:min 0, max 214
}

2. 函数参数特性

(1)外部参数名
  • 为参数添加外部名(调用时需显式传入),语法:func 函数名(外部名 内部名: 类型) -> 返回类型
  • 若外部名与内部名相同,可简写为 #内部名(Swift 3+ 推荐显式写外部名)。
Swift 复制代码
// 外部参数名:firstArg(外部)、a(内部);secondArg(外部)、b(内部)
func pow(firstArg a: Int, secondArg b: Int) -> Int {
    var res = a
    for _ in 1..<b {
        res *= a
    }
    print("result = \(res)")
    return res
}
pow(firstArg: 2, secondArg: 10) // 调用时必须传入外部名,输出:1024
(2)可变参数
  • 允许传入任意个数的相同类型参数,语法:参数名: 类型...(函数内部视为数组)。
Swift 复制代码
// 泛型可变参数(支持任意类型)
func vari<N>(members: N...) {
    for i in members {
        print(i, terminator: " ")
    }
    print()
}
vari(members: 1, 2, 3, 4, 5) // 输出:1 2 3 4 5
vari(members: 4.5, 3.1, 5.6) // 输出:4.5 3.1 5.6
vari(members: "sdsad", "324", "x", "admin", "abc") // 输出:sdsad 324 x admin abc
(3)输入输出参数(inout
  • 允许函数修改外部变量的值(需传入变量地址 &),语法:inout 参数名: 类型
Swift 复制代码
// 交换两个 Int 变量的值
func swapTwoInts(_ a: inout Int, _ b: inout Int) { // _ 表示省略外部名
    let temporaryA = a
    a = b
    b = temporaryA
}

var x = 10, y = 20
swapTwoInts(&x, &y) // 传入变量地址
print("x = \(x) , y = \(y)") // 输出:x = 20 , y = 10

3. 函数类型与高阶函数

(1)函数类型
  • 函数也是一种类型,格式:(参数类型列表) -> 返回类型,可赋值给变量/常量。
Swift 复制代码
// 定义函数类型变量(匹配 pow 函数的类型:(Int, Int) -> Int)
var powFunc: (Int, Int) -> Int = pow
powFunc(2, 5) // 调用,输出:32
(2)函数作为参数/返回值
  • 函数可作为参数传入其他函数,或作为返回值返回(高阶函数特性)。
Swift 复制代码
// 函数作为参数
func sum(a: Int, b: Int) -> Int {
    return a + b
}
func another(addition: (Int, Int) -> Int, a: Int, b: Int) {
    print("输出结果: \(addition(a, b))")
}
another(addition: sum, a: 40, b: 89) // 输出:129

// 函数作为返回值(嵌套函数)
func calcDecrement(forDecrement total: Int) -> () -> Int {
    var overallDecrement = 0
    // 嵌套函数:捕获外部变量 overallDecrement(闭包特性)
    func decrementer() -> Int {
        overallDecrement -= total
        return overallDecrement
    }
    return decrementer // 返回嵌套函数
}

let decrem = calcDecrement(forDecrement: 30)
print(decrem()) // 输出:-30
print(decrem()) // 输出:-60(状态被保留)

1.7 闭包(Closure)

闭包是"自包含的函数代码块",可捕获外部变量,支持语法简化,是 Swift 高阶特性的核心。

1. 闭包基本定义

  • 语法:{ (参数列表) -> 返回类型 in 闭包体 }in 分隔参数/返回值与闭包体。
Swift 复制代码
// 1. 无参数无返回值闭包
let studname = { print("Swift 闭包实例") }
studname() // 输出:Swift 闭包实例

// 2. 有参数有返回值闭包
let divide = { (val1: Int, val2: Int) -> Int in
    return val1 / val2
}
print(divide(2, 1)) // 输出:2

2. 闭包语法简化

Swift 对闭包有多重简化规则,核心是"能省则省":

(1)类型推断(省略参数类型与返回类型)

若上下文可推断出参数类型和返回类型,可省略。

Swift 复制代码
// 原闭包:sorted(by: {(s1: Int, s2: Int) -> Bool in return s1 < s2})
let sortedValues = [2, 3423, 234, 23, 3]
// 简化后:省略参数类型和返回类型(上下文推断为 (Int, Int) -> Bool)
let resultValues = sortedValues.sorted(by: { s1, s2 in s1 < s2 })
(2)参数缩写($0$1$2...)

$0 表示第一个参数,$1 表示第二个参数,以此类推,可省略参数列表和 in

Swift 复制代码
// 进一步简化:用 $0、$1 代替参数
let resultValues2 = sortedValues.sorted(by: { $0 < $1 })
(3)尾随闭包(Trailing Closure)

若闭包是函数的最后一个参数,可将闭包写在函数括号外,甚至省略括号。

Swift 复制代码
// 尾随闭包写法(闭包在括号外)
let resultValues3 = sortedValues.sorted { $0 < $1 }
// 若函数无其他参数,可省略括号:sorted { $0 < $1 }
(4)运算符函数简化

若闭包体仅调用一个二元运算符,可直接传入运算符函数。

Swift 复制代码
// 最终简化:< 是 (Int, Int) -> Bool 类型的运算符函数
let resultValues4 = sortedValues.sorted(by: <)
print(resultValues4) // 输出:[2, 3, 23, 234, 3423]

3. 闭包捕获值

闭包可捕获外部作用域的变量/常量,即使外部作用域销毁,捕获的值仍可访问(捕获机制由 ARC 管理)。

Swift 复制代码
var capturedValue = 100
func makeIncrementor(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0 // 外部变量,被闭包捕获
    func incrementor() -> Int {
        runningTotal += amount // 捕获 runningTotal
        return runningTotal
    }
    return incrementor
}

// 闭包捕获 runningTotal,状态被保留
let incrementByTen = makeIncrementor(forIncrement: capturedValue)
print(incrementByTen()) // 输出:100
print(incrementByTen()) // 输出:200(runningTotal 累计)

// 多个闭包共享同一捕获值
let alsoIncrementByTen = incrementByTen
print(alsoIncrementByTen()) // 输出:300(与 incrementByTen 共享 runningTotal)

1.8 枚举(Enumeration)

枚举是"一组相关值的集合",Swift 枚举支持关联值、原始值、方法等高级特性。

1. 枚举基本定义

  • 语法:enum 枚举名 { case 成员1, 成员2, ... },成员无默认值(需显式关联或指定原始值)。
Swift 复制代码
enum DayOfWeek {
    case Sunday, Monday, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, Saturday
}

// 使用枚举
var weekDay: DayOfWeek // 延迟初始化
weekDay = .Sunday // 类型可推断时,可省略枚举名

// switch 匹配枚举(需覆盖所有成员或加 default)
switch weekDay {
case .Sunday: print("星期天")
case .Monday: print("星期一")
case .TUESDAY: print("星期二")
// ... 其他成员
default: print("其他星期")
}

2. 枚举关联值(Associated Values)

  • 为枚举成员关联自定义类型的值,类似"带参数的枚举",常用于表示"同一抽象类型的不同具体情况"。
Swift 复制代码
// 枚举关联值:表示学生的两种信息(姓名/分数)
enum Student {
    case Name(String) // 关联 String 类型
    case Mark(Int, Int, Int) // 关联三个 Int 类型
}

// 赋值关联值
var studDetails = Student.Name("Runoob")
var studMarks = Student.Mark(98, 97, 95)

// 提取关联值(switch 绑定)
switch studMarks {
case .Name(let studName):
    print("学生的名字是: \(studName)。")
case .Mark(let Mark1, let Mark2, let Mark3):
    print("学生的成绩是: \(Mark1),\(Mark2),\(Mark3)。") // 输出:98,97,95
}

3. 枚举原始值(Raw Values)

  • 为枚举成员指定默认值(所有成员的原始值类型相同),支持自动递增(如 Int 类型),原始值可通过 rawValue 属性访问。
Swift 复制代码
// 枚举原始值:Int 类型,January 为 1,后续成员自动 +1
enum Month: Int {
    case January = 1, February, March, April, May, June, July, August, September, October, November, December
}

// 访问原始值
let yearMonthRaw = Month.February.rawValue
print("yearMonthRaw = \(yearMonthRaw)") // 输出:2

// 通过原始值创建枚举实例(返回可选类型,需解包)
if let december = Month(rawValue: 12) {
    print("December 的原始值是 \(december.rawValue)") // 输出:12
}

4. 枚举方法

枚举可定义实例方法和类型方法,支持 mutating 关键字(修改枚举自身值)。

Swift 复制代码
enum Days: Daysofaweek { // Daysofaweek 是自定义协议
    case sun, mon, tue, wed, thurs, fri, sat
    
    // 实例方法,mutating 修饰(修改枚举自身)
    mutating func show() {
        switch self {
        case .sun:
            self = .sun
            print("Sunday")
        case .mon:
            self = .mon
            print("Monday")
        // ... 其他成员
        }
    }
}

var res = Days.wed
res.show() // 输出:Wednesday

1.9 结构体与类(Struct & Class)

结构体和类是 Swift 中封装数据和行为的核心类型,核心区别是值类型 vs 引用类型

1. 区别对比

特性 结构体(Struct) 类(Class)
类型本质 值类型(赋值/传参时深拷贝) 引用类型(赋值/传参时传内存地址)
继承 不支持 支持(单继承)
初始化器 自动生成成员初始化器 需显式定义(除非所有属性有默认值)
析构器(deinit) 不支持 支持
引用计数(ARC) 有(管理实例生命周期)
常量实例可变性 不可修改任何属性(即使 var) 可修改 var 属性(let 仅限制引用)
mutating 方法 修改属性需加 mutating 无需加 mutating

2. 结构体示例

Swift 复制代码
// 结构体定义(自动生成成员初始化器)
struct Marks {
    var mark1: Int = 100
    var mark2: Int = 200
    var mark3: Int = 300
}

// 使用自动生成的成员初始化器
let mark = Marks()
print("mark1 = \(mark.mark1)") // 输出:100

// 结构体带自定义初始化器
struct MarkStruct {
    var mark1: Int, mark2: Int, mark3: Int
    // 自定义初始化器(需初始化所有属性)
    init(mark1: Int, mark2: Int, mark3: Int) {
        self.mark1 = mark1
        self.mark2 = mark2
        self.mark3 = mark3
    }
}

// 结构体方法的 mutating(修改属性必需)
struct Area {
    var length = 1, breadth = 1
    // 修改属性的方法需加 mutating
    mutating func scaleBy(res: Int) {
        length *= res
        breadth *= res
    }
}

var val = Area(length: 3, breadth: 5)
val.scaleBy(res: 3)
print("length = \(val.length), breadth = \(val.breadth)") // 输出:9, 15

3. 类示例

Swift 复制代码
// 类定义(需显式定义初始化器)
class MarksStruct {
    var mark: Int
    // 自定义初始化器
    init(mark: Int) {
        self.mark = mark
    }
}

// 类的继承与方法重写
class SuperClass {
    func show() {
        print("这是超类 SuperClass")
    }
}

class SubClass: SuperClass {
    // 重写父类方法需加 override
    override func show() {
        print("这是子类 SubClass")
    }
}

// 类的引用特性(=== 判断引用是否相同)
let superObj = SuperClass()
let subObj = SubClass()
let subObj2 = subObj // 传引用,subObj 与 subObj2 指向同一实例
print(subObj === subObj2) // 输出:true(引用相同)

// 类的析构器(deinit,实例销毁前执行)
class FileHandler {
    let filename: String
    init(filename: String) {
        self.filename = filename
        print("打开文件:\(filename)")
    }
    deinit {
        print("关闭文件:\(filename)")
    }
}

// 超出作用域时,析构器自动调用
func openFile() {
    let handler = FileHandler(filename: "test.txt")
}
openFile() // 输出:打开文件:test.txt → 关闭文件:test.txt

1.10 属性(Property)

属性是"关联到类型或实例的值",分为存储属性 (存储数据)和计算属性(计算数据),支持属性观察器。

1. 存储属性(Stored Property)

  • 直接存储值,适用于结构体和类,支持 let(不可变)和 var(可变)。
Swift 复制代码
class Person {
    let name: String // 不可变存储属性(初始化后不可改)
    var age: Int // 可变存储属性
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}

let person = Person(name: "小明", age: 18)
person.age = 19 // 合法(var 可变)
// person.name = "小红" // 错误(let 不可变)、
延迟存储属性(lazy
  • lazy 修饰,延迟到第一次访问时才初始化(仅适用于 var,且必须有默认值或在初始化器中赋值)。
Swift 复制代码
class MyNumber {
    var name = "This is a number"
}

class Sample {
    // 延迟属性:第一次访问 no 时才初始化 MyNumber 实例
    lazy var no = MyNumber()
}

let firstSample = Sample()
print(firstSample.no.name) // 第一次访问,初始化 MyNumber,输出:This is a number

2. 计算属性(Computed Property)

  • 不直接存储值,通过 get(读取)和 set(写入)计算值,适用于结构体、类、枚举。
  • 只读计算属性:省略 setget 关键字,直接返回计算结果。
Swift 复制代码
class Sampl2 {
    var no1: Double = 0, no2: Double = 0
    var length = 300.0, breadth = 150.0
    
    // 读写计算属性(get + set)
    var middle: (Double, Double) {
        get {
            return (length / 2, breadth / 2) // 读取时计算
        }
        set(axis) { // axis 是新值的参数名,默认是 newValue
            no1 = axis.0 - (length / 2)
            no2 = axis.1 - (breadth / 2)
        }
    }
    
    // 只读计算属性(省略 get)
    var area: Double {
        return length * breadth // 仅支持读取
    }
}

let mSample2 = Sampl2()
print(mSample2.middle) // 调用 get,输出:(150.0, 75.0)
mSample2.middle = (0, 10) // 调用 set,修改 no1 和 no2
print(mSample2.no1) // 输出:-150.0
print(mSample2.area) // 调用只读计算属性,输出:45000.0

3. 属性观察器(Property Observers)

  • 监控属性值的变化,触发 willSet(值修改前)和 didSet(值修改后),适用于存储属性(包括继承的存储属性)。
Swift 复制代码
class Samplepgm {
    var counter: Int = 0 {
        willSet(newTotal) { // newTotal 是新值(默认参数名)
            print("计数器即将变为:\(newTotal)")
        }
        didSet(oldValue) { // oldValue 是旧值(默认参数名)
            if counter > oldValue {
                print("新增数:\(counter - oldValue)")
            }
        }
    }
}

let newCounter = Samplepgm()
newCounter.counter = 100 // 触发 willSet(100)和 didSet(0→100)
// 输出:
// 计数器即将变为:100
// 新增数:100

4. 类型属性(Type Properties)

  • 属于类型本身,而非实例,所有实例共享,用 static(结构体、枚举、类)或 class(仅类,支持重写)修饰。
Swift 复制代码
// 结构体的类型属性(static)
struct Student2 {
    static let totalCount: Int = 0 // 不可变类型属性(所有学生共享)
    var name: String // 实例属性(每个学生独有)
}

// 类的类型属性(static 不可重写,class 可重写)
class School {
    static let maxStudents: Int = 1000 // 不可重写
    class var schoolName: String { // 可重写的计算类型属性
        return "Swift 学校"
    }
}

// 访问类型属性(通过类型名,而非实例)
print(Student2.totalCount) // 输出:0
print(School.maxStudents) // 输出:1000
print(School.schoolName) // 输出:Swift 学校

1.11 方法(Method)

方法是"关联到类型或实例的函数",分为实例方法 (属于实例)和类型方法(属于类型)。

1. 实例方法(Instance Methods)

  • 属于实例,需通过实例调用,可访问实例属性和其他实例方法。
Swift 复制代码
class Counter {
    var count = 0
    // 实例方法:修改实例属性
    func increment() {
        count += 1
    }
    // 带参数的实例方法
    func incrementBy(amount: Int) {
        count += amount
    }
    // 无参数无返回值的实例方法
    func reset() {
        count = 0
    }
}

let counter = Counter()
counter.increment() // 调用实例方法,count = 1
counter.incrementBy(amount: 5) // count = 6
print(counter.count) // 输出:6
counter.reset() // count = 0

2. 类型方法(Type Methods)

  • 属于类型,用 static(结构体、枚举、类)或 class(仅类,支持重写)修饰,通过类型名调用,可访问类型属性。
Swift 复制代码
// 结构体的类型方法(static)
struct Math {
    static func abs(number: Int) -> Int {
        return number < 0 ? -number : number
    }
}

// 类的类型方法(class,可重写)
class Calculator {
    class func add(a: Int, b: Int) -> Int {
        return a + b
    }
}

// 调用类型方法(通过类型名)
print(Math.abs(number: -100)) // 输出:100
print(Calculator.add(a: 10, b: 20)) // 输出:30

3. 结构体方法的 mutating

  • 结构体是值类型,默认实例方法不能修改实例属性,需用 mutating 修饰(类无需)。
Swift 复制代码
struct Area {
    var length = 1, breadth = 1
    // mutating 方法:修改结构体实例属性
    mutating func scaleBy(res: Int) {
        length *= res
        breadth *= res
    }
}

var area = Area(length: 3, breadth: 5)
area.scaleBy(res: 2)
print("length = \(area.length), breadth = \(area.breadth)") // 输出:6, 10

1.12 下标脚本(Subscript)

下标脚本是"通过 [] 访问类型实例的语法",类似数组和字典的下标,支持自定义参数和返回值。

1. 下标脚本基本定义

  • 语法:subscript(参数列表) -> 返回类型 { get { ... } set(newValue) { ... } },支持只读(省略 set)。
Swift 复制代码
// 结构体下标:通过下标返回"数值除以索引"的结果
struct SubExample {
    let decrementer: Int
    // 只读下标(省略 set)
    subscript(index: Int) -> Int {
        return decrementer / index
    }
    init(decrementer: Int) {
        self.decrementer = decrementer
    }
}

let division = SubExample(decrementer: 100)
print("100 / 9 = \(division[9])") // 输出:11
print("100 / 2 = \(division[2])") // 输出:50

2. 类的下标(支持读写)

Swift 复制代码
// 类下标:模拟数组的读写功能
class DaysOfAWeek {
    private var days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
    // 读写下标
    subscript(index: Int) -> String {
        get {
            return days[index] // 读取
        }
        set(newValue) {
            days[index] = newValue // 写入
        }
    }
}

let week = DaysOfAWeek()
print(week[1]) // 调用 get,输出:Monday
week[1] = "星期一" // 调用 set
print(week[1]) // 输出:星期一

3. 多参数下标

下标支持多个参数,适用于多维数据结构(如二维矩阵)。

Swift 复制代码
// 二维矩阵的多参数下标
struct Matrix {
    let rows: Int, columns: Int
    var values: [Double]
    init(rows: Int, columns: Int) {
        self.rows = rows
        self.columns = columns
        values = Array(repeating: 0.0, count: rows * columns)
    }
    // 双参数下标(row: 行,column: 列)
    subscript(row: Int, column: Int) -> Double {
        get {
            return values[row * columns + column]
        }
        set {
            values[row * columns + column] = newValue
        }
    }
}

var mat = Matrix(rows: 4, columns: 4)
mat[0, 0] = 1.0
mat[1, 1] = 2.0
print("mat[0,0] = \(mat[0,0])") // 输出:1.0
print("mat[1,1] = \(mat[1,1])") // 输出:2.0

资料分享:https://github.com/0voice

相关推荐
csbysj20201 小时前
Vue3 事件处理
开发语言
Q***f6351 小时前
Kotlin在Android性能优化中的工具
android·开发语言·kotlin
菠菠萝宝2 小时前
【Java手搓RAGFlow】-9- RAG对话实现
java·开发语言·人工智能·llm·jenkins·openai
leon_zeng02 小时前
Qt OpenGL 3D 彩色立方体开发指南
开发语言·qt
科威舟的代码笔记2 小时前
第10讲:Stream实战与陷阱——综合案例与最佳实践
java·开发语言
MM_MS2 小时前
WinForm+C#小案例--->爱心跑马灯演示
开发语言·c#·visual studio
福尔摩斯张2 小时前
C语言核心:string函数族处理与递归实战
c语言·开发语言·数据结构·c++·算法·c#
程序定小飞2 小时前
基于springboot的体育馆使用预约平台的设计与实现
java·开发语言·spring boot·后端·spring
大佬,救命!!!2 小时前
最新的python3.14版本下仿真环境配置深度学习机器学习相关
开发语言·人工智能·python·深度学习·机器学习·学习笔记·环境配置