返回

Swift 中的类与结构体(上)

IOS

结构体与类:Swift 中构建应用程序的基本组成部分

在 Swift 编程语言中,结构体和类扮演着构建应用程序的关键角色。它们提供了创建和组织数据的强大机制,但它们也有一些微妙的差异,理解这些差异对于编写高效且健壮的代码至关重要。

值类型与引用类型

最根本的区别在于结构体是值类型,而类是引用类型。这意味着当您创建一个结构体的实例时,Swift 会创建一个该实例的副本并将其存储在栈内存中。对副本进行的任何修改都不会影响原始结构体。相反,当您创建一个类的实例时,Swift 会在堆内存中创建一个指向该实例的引用。对该引用的修改会影响原始类实例。

示例:

struct Point {
    var x: Int
    var y: Int
}

var point1 = Point(x: 10, y: 20)
var point2 = point1

point2.x = 30 // 仅修改 point2 的副本,不影响 point1

class Person {
    var name: String
    var age: Int
}

var person1 = Person(name: "John", age: 30)
var person2 = person1

person2.name = "Mary" // 修改 person2 的引用,也会修改 person1

方法调度

另一个关键差异是方法调度。对于结构体,方法总是直接在实例上调用,类似于值类型在其他编程语言中的行为。这使结构体的方法实现与该特定实例绑定。另一方面,对于类,方法可以在实例或其类型上调用。这意味着类的实现与类型本身绑定,而不是与特定实例绑定。

示例:

struct Point {
    func distanceToOrigin() -> Double {
        return sqrt(Double(x * x + y * y))
    }
}

class Person {
    class func greet() {
        print("Hello, world!")
    }
}

let point = Point(x: 10, y: 20)
let distance = point.distanceToOrigin() // 直接在实例上调用方法

Person.greet() // 在类型上调用方法

插件使用

libfooplugin 是一个开源 Swift 插件,用于演示结构体和类之间的差异。该插件为结构体和类提供了相同的方法,但实现方式不同。对于结构体,方法在实例上直接调用,而对于类,方法在类型上调用。

示例:

import libfooplugin

let point = Point(x: 10, y: 20)
let result = point.foo() // 直接在实例上调用 foo()

let person = Person(name: "John", age: 30)
let result = person.foo() // 在类型上调用 foo()

通过使用 libfooplugin,您可以看到结构体和类之间方法调度的差异。

结论

结构体和类是构建 Swift 应用程序的基本组成部分。它们共享许多特性,例如封装和方法,但它们在值类型与引用类型、方法调度和内存管理方面存在关键差异。了解这些差异对于编写健壮且高效的 Swift 代码至关重要。选择正确的类型将帮助您优化应用程序的性能和内存使用情况。

常见问题解答

  1. 什么时候应该使用结构体?

    • 当您需要一个值类型时,即当您需要创建一个不会意外更改数据的副本时。
  2. 什么时候应该使用类?

    • 当您需要一个引用类型时,即当您希望对实例的修改反映在所有引用该实例的地方时。
  3. 结构体比类更有效率吗?

    • 是的,结构体通常比类更有效率,因为它们存储在栈内存中,不需要引用开销。
  4. 类可以继承吗?

    • 是的,类可以继承自其他类,允许您创建层次结构并重用代码。
  5. 结构体可以继承吗?

    • 否,结构体不能继承自其他结构体或类。