在 Swift 中,struct(结构体)和 class(类)是两种重要的数据类型,它们有一些相似的地方,但也有许多关键的区别。以下是它们的主要区别:

1. 值类型 vs 引用类型

  • 结构体(struct):是值类型。当你创建一个结构体的实例并将其赋值给一个变量或常量,或者将其传递给一个函数时,实际上是创建了这个结构体的一个副本。每个副本都是独立的,修改一个副本不会影响其他副本。

    struct Point {
        var x: Int
        var y: Int
    }
    
    var point1 = Point(x: 0, y: 0)
    var point2 = point1
    point2.x = 10
    
    print(point1.x) // 输出 0
    print(point2.x) // 输出 10
    
  • 类(class):是引用类型。当你创建一个类的实例并将其赋值给一个变量或常量,或者将其传递给一个函数时,实际上是传递了这个类的引用。多个变量或常量可以引用同一个类实例,修改一个引用会影响所有引用。

    class Point {
        var x: Int
        var y: Int
    
        init(x: Int, y: Int) {
            self.x = x
            self.y = y
        }
    }
    
    var point1 = Point(x: 0, y: 0)
    var point2 = point1
    point2.x = 10
    
    print(point1.x) // 输出 10
    print(point2.x) // 输出 10
    

2. 继承

  • 结构体(struct):不支持继承。你不能从一个结构体继承另一个结构体。

    struct A {
        var value: Int
    }
    
    // struct B: A { // 错误,结构体不支持继承
    // }
    
  • 类(class):支持继承。你可以从一个类继承另一个类,并且可以重写父类的方法和属性。

    class Animal {
        func makeSound() {
            print("Some generic animal sound")
        }
    }
    
    class Dog: Animal {
        override func makeSound() {
            print("Bark")
        }
    }
    
    let myDog = Dog()
    myDog.makeSound() // 输出 "Bark"
    

3. 构造器

  • 结构体(struct):自动生成成员逐一构造器,你可以直接使用它来初始化结构体的实例。

    struct Point {
        var x: Int
        var y: Int
    }
    
    let point = Point(x: 10, y: 20)
    
  • 类(class):不会自动生成成员逐一构造器,你需要自己定义构造器。

    class Point {
        var x: Int
        var y: Int
    
        init(x: Int, y: Int) {
            self.x = x
            self.y = y
        }
    }
    
    let point = Point(x: 10, y: 20)
    

4. 引用计数和内存管理

  • 结构体(struct):由于是值类型,结构体不涉及引用计数和垃圾回收。

  • 类(class):作为引用类型,类实例由引用计数管理。Swift 使用自动引用计数(ARC)来管理类实例的内存。

5. 可变性

  • 结构体(struct):如果你定义了一个结构体实例为常量(let),那么它的所有属性也都是不可变的,即使这些属性是变量(var)。

    struct Point {
        var x: Int
        var y: Int
    }
    
    let point = Point(x: 10, y: 20)
    // point.x = 30 // 错误,point 是常量
    
  • 类(class):如果你定义了一个类实例为常量(let),你仍然可以修改它的可变属性(var)。

    class Point {
        var x: Int
        var y: Int
    
        init(x: Int, y: Int) {
            self.x = x
            self.y = y
        }
    }
    
    let point = Point(x: 10, y: 20)
    point.x = 30 // 正确,尽管 point 是常量
    

6. 协议一致性

  • 结构体(struct):可以通过扩展(extension)来遵循协议,并且可以在扩展中添加默认实现。

  • 类(class):同样可以通过扩展来遵循协议,并且可以在扩展中添加默认实现。

总结来说,选择使用 struct 还是 class 取决于你的需求。如果你需要值语义(每次赋值或传递时创建副本)和简单的数据封装,使用 struct。如果你需要引用语义(多个引用指向同一个实例)、继承和更复杂的对象行为,使用 class

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐