Swift 类

Swift 中的类(Class)引用类型(Reference Type),用于创建具有继承、引用语义、身份比较等特性的对象。它适合建模复杂对象、控制器、共享状态等场景。


基本语法

class 类名: 超类?, 协议1, 协议2... {
    // 属性
    var property: Type
    let constant: Type

    // 初始化器
    init(parameters) { ... }

    // 析构器
    deinit { ... }

    // 方法
    func method() { ... }
}

示例:车辆类

class Vehicle {
    var numberOfWheels: Int
    var currentSpeed: Double = 0.0

    init(wheels: Int) {
        self.numberOfWheels = wheels
    }

    func accelerate(by amount: Double) {
        currentSpeed += amount
    }

    func description() -> String {
        return "这辆车有 \(numberOfWheels) 个轮子,当前速度 \(currentSpeed) km/h"
    }
}

// 继承
class Bicycle: Vehicle {
    var hasBasket = false

    init(hasBasket: Bool = false) {
        self.hasBasket = hasBasket
        super.init(wheels: 2)
        self.currentSpeed = 0
    }

    override func description() -> String {
        return super.description() + (hasBasket ? ",带篮子" : "")
    }
}

let bike = Bicycle(hasBasket: true)
bike.accelerate(by: 15)
print(bike.description())
// 这辆车有 2 个轮子,当前速度 15.0 km/h,带篮子

核心特性对比(类 vs 结构体)

特性结构体
类型引用类型值类型
赋值共享引用复制副本
继承支持不支持
析构器 deinit支持不支持
身份比较 ===支持不支持
内存管理ARC 自动引用计数栈/堆(Copy-on-Write)
多态支持不支持

1. 引用语义(关键!)

class Person {
    var name: String
    init(name: String) { self.name = name }
    func sayHello() { print("Hi, I'm \(name)") }
}

let p1 = Person(name: "Alice")
let p2 = p1        // 同一个对象!
p2.name = "Bob"

p1.sayHello()      // Hi, I'm Bob
print(p1 === p2)   // true(同一实例)

结构体则会复制:

struct Point { var x = 0, y = 0 }
var s1 = Point(x: 1, y: 2)
var s2 = s1
s2.x = 99
print(s1.x) // 1(独立副本)

2. 初始化器(Initializer)

指定初始化器(Designated)

class User {
    var id: Int
    var name: String

    init(id: Int, name: String) {
        self.id = id
        self.name = name
    }
}

便利初始化器(Convenience)

class User {
    var id: Int
    var name: String

    init(id: Int, name: String) {
        self.id = id
        self.name = name
    }

    convenience init(name: String) {
        self.init(id: 0, name: name)
    }
}

let user = User(name: "Tom")  // 使用便利初始化器

两阶段初始化(Two-Phase Initialization)

  1. 初始化所有存储属性(包括继承的)
  2. 调用 super.init
class Animal {
    var species: String
    init(species: String) { self.species = species }
}

class Dog: Animal {
    var breed: String
    init(breed: String) {
        self.breed = breed        // 第1阶段:初始化自身属性
        super.init(species: "Canine")  // 第2阶段:调用父类
    }
}

3. 析构器(deinit)

class FileHandler {
    let filename: String

    init(filename: String) {
        self.filename = filename
        print("打开文件: \(filename)")
    }

    deinit {
        print("关闭文件: \(filename)")
    }
}

var file: FileHandler? = FileHandler(filename: "data.txt")
file = nil  // 触发 deinit
// 打开文件: data.txt
// 关闭文件: data.txt

结构体无 deinit


4. 方法重写(Override)

class Shape {
    func draw() -> String {
        return "绘制形状"
    }
}

class Circle: Shape {
    var radius: Double

    init(radius: Double) { self.radius = radius }

    override func draw() -> String {
        return "绘制圆,半径 \(radius)"
    }
}

5. 属性重写

class Car {
    var speed: Double { 0 }
}

class SportsCar: Car {
    private var _speed = 200.0
    override var speed: Double {
        get { _speed }
        set { _speed = min(newValue, 300) }
    }
}

6. 类型属性和方法

class Math {
    static let pi = 3.14159

    class func square(_ x: Double) -> Double {
        return x * x
    }
}

print(Math.pi)
print(Math.square(5))  // 25.0

class func 可被子类重写,static func 不可


7. 引用循环与弱引用

class Person {
    var name: String
    var apartment: Apartment?
    init(name: String) { self.name = name }
    deinit { print("\(name) 被释放") }
}

class Apartment {
    var number: Int
    weak var tenant: Person?  // weak 打破循环
    // unowned var tenant: Person?  // 另一种方式
    init(number: Int) { self.number = number }
    deinit { print("公寓 \(number) 被释放") }
}

var john: Person? = Person(name: "John")
var unit4A: Apartment? = Apartment(number: 4)

john?.apartment = unit4A
unit4A?.tenant = john

john = nil
unit4A = nil
// John 被释放
// 公寓 4 被释放

weak/unowned 会导致内存泄漏


8. final 关键字

final class ImmutablePoint {
    let x: Double
    let y: Double
    init(x: Double, y: Double) {
        self.x = x
        self.y = y
    }
}
// 不能被继承

9. 类与协议

protocol Resettable {
    func reset()
}

class Counter: Resettable {
    var count = 0
    func reset() { count = 0 }
}

10. AnyObject 和类型转换

class Animal { }
class Dog: Animal { func bark() { print("Woof") } }
class Cat: Animal { func meow() { print("Meow") } }

let pets: [AnyObject] = [Dog(), Cat(), Dog()]

for pet in pets {
    if let dog = pet as? Dog {
        dog.bark()
    }
}

最佳实践总结

场景推荐使用类
需要继承
需要引用语义(共享状态)
需要 deinit 清理资源
实现 Cocoa 框架(如 UIViewController
身份重要(=== 比较)
场景推荐使用结构体
简单数据模型结构体
复制安全结构体
无继承需求结构体
性能敏感结构体

常见面试题

  1. 类和结构体的赋值行为有何不同?
    → 类是引用传递(共享),结构体是值复制(独立)。
  2. 如何防止引用循环?
    → 使用 weakunowned 引用。
  3. 什么时候用 unowned vs weak
  • weak: 可选,可能为 nil
  • unowned: 必有值,生命周期明确,不为 nil
  1. class func vs static func
  • class func: 可被子类重写
  • static func: 不可重写

小技巧

// 单例模式
class AudioManager {
    static let shared = AudioManager()
    private init() { }  // 防止外部创建
}

// 延迟初始化
class DataService {
    lazy var database = Database()
}

高级话题(可继续提问)

  • 值类型 vs 引用类型的 Copy-on-Write 优化
  • Actor 模型(并发安全类)
  • 类簇(Class Cluster)
  • KVO / Notification 与类
  • SwiftUI 中的 @Observable

需要代码示例、性能分析、或与 Actor 对比?欢迎继续提问!

文章已创建 2481

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部